Skip to content

Commit c64e73d

Browse files
authored
docs(mcp): improve MCP docs including auto-generated pdocs (#806)
1 parent 20bb0a8 commit c64e73d

File tree

6 files changed

+179
-88
lines changed

6 files changed

+179
-88
lines changed

airbyte/mcp/__init__.py

Lines changed: 80 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,72 @@
22

33
r"""***PyAirbyte MCP Server - Model Context Protocol Integration***
44
5+
> **NOTE:**
6+
> This MCP server implementation is experimental and may change without notice between minor
7+
> versions of PyAirbyte. The API may be modified or entirely refactored in future versions.
8+
59
The PyAirbyte MCP (Model Context Protocol) server provides a standardized interface for
610
managing Airbyte connectors through MCP-compatible clients. This experimental feature
711
allows you to list connectors, validate configurations, and run sync operations using
812
the MCP protocol.
913
10-
The Model Context Protocol (MCP) is an open standard that enables AI assistants and
11-
other tools to securely connect to data sources, tools, and services. PyAirbyte's MCP
12-
server implementation allows you to build and interact with Airbyte connectors through
13-
this standardized protocol.
14+
## Getting Started with PyAirbyte MCP
1415
15-
Create a JSON configuration file to register the PyAirbyte MCP server with your MCP
16-
client. Create a file named `server_config.json`:
16+
To get started with the PyAirbyte MCP server, follow these steps:
1717
18-
> **NOTE:**
19-
> This MCP server implementation is experimental and may change without notice between minor
20-
> versions of PyAirbyte. The API may be modified or entirely refactored in future versions.
18+
1. Create a Dotenv secrets file.
19+
2. Register the MCP server with your MCP client.
20+
3. Test the MCP server connection using your MCP client.
21+
22+
### Step 1: Generate a Dotenv Secrets File
23+
24+
To get started with the PyAirbyte MCP server, you will need to create a dotenv
25+
file containing your Airbyte Cloud credentials, as well as credentials for any
26+
third-party services you wish to connect to via Airbyte.
27+
28+
Create a file named `~/.mcp/airbyte_mcp.env` with the following content:
29+
30+
```ini
31+
# Airbyte Project Artifacts Directory
32+
AIRBYTE_PROJECT_DIR=/path/to/any/writeable/project-dir
2133
22-
# MCP Server Configuration
34+
# Airbyte Cloud Credentials (Required for Airbyte Cloud Operations)
35+
AIRBYTE_CLOUD_CLIENT_ID=your_api_key
36+
AIRBYTE_CLOUD_CLIENT_SECRET=your_api_secret
37+
AIRBYTE_CLOUD_WORKSPACE_ID=your_workspace_id
2338
24-
Assuming `uv` is installed, you can use the following configuration:
39+
# API-Specific Credentials (Optional, depending on your connectors)
40+
41+
# For example, for a PostgreSQL source connector:
42+
# POSTGRES_HOST=your_postgres_host
43+
# POSTGRES_PORT=5432
44+
# POSTGRES_DB=your_database_name
45+
# POSTGRES_USER=your_database_user
46+
# POSTGRES_PASSWORD=your_database_password
47+
48+
# For example, for a Stripe source connector:
49+
# STRIPE_API_KEY=your_stripe_api_key
50+
# STRIPE_API_SECRET=your_stripe_api_secret
51+
# STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret
52+
```
53+
54+
Note:
55+
1. You can add more environment variables to this file as needed for different connectors. To start,
56+
you only need to create the file and pass it to the MCP server.
57+
2. Ensure that this file is kept secure, as it contains sensitive information. Your LLM
58+
*should never* be given direct access to this file or its contents.
59+
3. The MCP tools will give your LLM the ability to view *which* variables are available, but it
60+
does not give access to their values.
61+
4. The `AIRBYTE_PROJECT_DIR` variable specifies a directory where the MCP server can
62+
store temporary project files. Ensure this directory is writable by the user running
63+
the MCP server.
64+
65+
### Step 2: Registering the MCP Server
66+
67+
First install `uv` (`brew install uv`).
68+
69+
Then, create a file named `server_config.json` (or the file name required by your MCP client)
70+
with the following content:
2571
2672
```json
2773
{
@@ -30,7 +76,7 @@
3076
"command": "uvx",
3177
"args": ["--from=airbyte", "airbyte-mcp"],
3278
"env": {
33-
"AIRBYTE_MCP_ENV_FILE": "~/.mcp/airbyte_mcp.env"
79+
"AIRBYTE_MCP_ENV_FILE": "/path/to/my/.mcp/airbyte_mcp.env"
3480
}
3581
}
3682
}
@@ -47,95 +93,53 @@
4793
"command": "airbyte-mcp",
4894
"args": [],
4995
"env": {
50-
"AIRBYTE_MCP_ENV_FILE": "~/.mcp/airbyte_mcp.env"
96+
"AIRBYTE_MCP_ENV_FILE": "/path/to/my/.mcp/airbyte_mcp.env"
5197
}
5298
}
5399
}
54100
}
55101
```
56102
57-
## Testing the MCP Server
58-
59-
60-
The easiest way to test PyAirbyte MCP tools during development is using the built-in Poe tasks.
61-
These tasks automatically inherit environment variables from your shell session:
62-
63-
```bash
64-
poe mcp-tool-test <tool_name> '<json_args>'
65-
66-
poe mcp-tool-test list_connectors '{}'
67-
poe mcp-tool-test get_config_spec '{"connector_name": "source-pokeapi"}'
68-
poe mcp-tool-test validate_config \
69-
'{"connector_name": "source-pokeapi", "config": {"pokemon_name": "pikachu"}}'
70-
poe mcp-tool-test run_sync \
71-
'{"connector_name": "source-pokeapi", "config": {"pokemon_name": "pikachu"}}'
72-
73-
poe mcp-tool-test check_airbyte_cloud_workspace '{}'
74-
poe mcp-tool-test list_deployed_cloud_connections '{}'
75-
```
76-
77-
78-
```bash
79-
poe mcp-serve-local # STDIO transport (default)
80-
poe mcp-serve-http # HTTP transport on localhost:8000
81-
poe mcp-serve-sse # Server-Sent Events transport on localhost:8000
82-
83-
poe mcp-inspect # Show all available MCP tools and their schemas
84-
```
103+
Note:
104+
- Replace `/path/to/my/.mcp/airbyte_mcp.env` with the absolute path to your dotenv file created in
105+
Step 1.
85106
107+
### Step 3: Testing the MCP Server Connection
86108
109+
You can test the MCP server connection using your MCP client.
87110
88-
## Contributing to PyAirbyte and the Airbyte MCP Server
111+
Helpful prompts to try:
89112
90-
The Airbyte MCP server is part of the PyAirbyte project. Contributions are welcome!
113+
1. "Use your MCP tools to list all available Airbyte connectors."
114+
2. "Use your MCP tools to get information about the Airbyte Stripe connector."
115+
3. "Use your MCP tools to list all variables you have access to in the dotenv secrets
116+
file."
117+
4. "Use your MCP tools to check your connection to your Airbyte Cloud workspace."
118+
5. "Use your MCP tools to list all available destinations in my Airbyte Cloud workspace."
91119
92-
You can contribute to the MCP server by adding new tools, improving existing functionality, or
93-
fixing bugs. The server is built using the FastMCP framework, which provides a flexible
94-
interface for defining tools and handling requests.
120+
## Contributing to the Airbyte MCP Server
95121
96-
As a starting point, you can clone the repo and inspect the server definition using the `fastmcp`
97-
CLI tool:
98-
99-
```bash
100-
poetry install --all-extras
101-
poetry run fastmcp inspect airbyte/mcp/server.py:app
102-
```
103-
104-
In your MCP config, you can test your development updates using `poetry` as the entrypoint:
105-
106-
```json
107-
{
108-
"mcpServers": {
109-
"airbyte": {
110-
"command": "poetry",
111-
"args": [
112-
"--directory=~/repos/PyAirbyte",
113-
"run",
114-
"airbyte-mcp"
115-
],
116-
"env": {
117-
"AIRBYTE_MCP_ENV_FILE": "~/.mcp/airbyte_mcp.env"
118-
}
119-
}
120-
}
121-
}
122-
```
122+
- [PyAirbyte Contributing Guide](https://github.com/airbytehq/PyAirbyte/blob/main/docs/CONTRIBUTING.md)
123123
124124
### Additional resources
125125
126126
- [Model Context Protocol Documentation](https://modelcontextprotocol.io/)
127127
- [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
128128
129129
For issues and questions:
130-
- [PyAirbyte Contributing Guide](https://github.com/airbytehq/PyAirbyte/blob/main/docs/CONTRIBUTING.md)
131130
- [PyAirbyte GitHub Issues](https://github.com/airbytehq/pyairbyte/issues)
132131
- [PyAirbyte Discussions](https://github.com/airbytehq/pyairbyte/discussions)
133132
134133
""" # noqa: D415
135134

136-
from airbyte.mcp import server
135+
from airbyte.mcp import cloud_ops, connector_registry, local_ops, server
137136

138137

139-
__all__: list[str] = ["server"]
138+
__all__: list[str] = [
139+
"cloud_ops",
140+
"connector_registry",
141+
"local_ops",
142+
"server",
143+
]
140144

141145
__docformat__ = "google"
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,10 @@ def list_deployed_cloud_connections() -> list[CloudConnection]:
502502

503503

504504
def register_cloud_ops_tools(app: FastMCP) -> None:
505-
"""Register tools with the FastMCP app."""
505+
"""@private Register tools with the FastMCP app.
506+
507+
This is an internal function and should not be called directly.
508+
"""
506509
app.tool(check_airbyte_cloud_workspace)
507510
app.tool(deploy_source_to_cloud)
508511
app.tool(deploy_destination_to_cloud)
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def list_connectors(
101101

102102

103103
class ConnectorInfo(BaseModel):
104-
"""Class to hold connector information."""
104+
"""@private Class to hold connector information."""
105105

106106
connector_name: str
107107
connector_metadata: ConnectorMetadata | None = None
@@ -110,6 +110,7 @@ class ConnectorInfo(BaseModel):
110110
manifest_url: str | None = None
111111

112112

113+
# @app.tool() # << deferred
113114
def get_connector_info(
114115
connector_name: Annotated[
115116
str,
@@ -151,6 +152,9 @@ def get_connector_info(
151152

152153

153154
def register_connector_registry_tools(app: FastMCP) -> None:
154-
"""Register tools with the FastMCP app."""
155+
"""@private Register tools with the FastMCP app.
156+
157+
This is an internal function and should not be called directly.
158+
"""
155159
app.tool(list_connectors)
156160
app.tool(get_connector_info)
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from airbyte.caches.duckdb import DuckDBCache
2626

2727

28-
CONFIG_HELP = """
28+
_CONFIG_HELP = """
2929
You can provide `config` as JSON or a Path to a YAML/JSON file.
3030
If a `dict` is provided, it must not contain hardcoded secrets.
3131
Instead, secrets should be provided using environment variables,
@@ -643,6 +643,7 @@ class CachedDatasetInfo(BaseModel):
643643
schema_name: str | None = None
644644

645645

646+
# @app.tool() # << deferred
646647
def list_cached_streams() -> list[CachedDatasetInfo]:
647648
"""List all streams available in the default DuckDB cache."""
648649
cache: DuckDBCache = get_default_cache()
@@ -658,6 +659,7 @@ def list_cached_streams() -> list[CachedDatasetInfo]:
658659
return result
659660

660661

662+
# @app.tool() # << deferred
661663
def describe_default_cache() -> dict[str, Any]:
662664
"""Describe the currently configured default cache."""
663665
cache = get_default_cache()
@@ -704,6 +706,7 @@ def _is_safe_sql(sql_query: str) -> bool:
704706
return any(normalized_query.startswith(prefix) for prefix in allowed_prefixes)
705707

706708

709+
# @app.tool() # << deferred
707710
def run_sql_query(
708711
sql_query: Annotated[
709712
str,
@@ -758,7 +761,10 @@ def run_sql_query(
758761

759762

760763
def register_local_ops_tools(app: FastMCP) -> None:
761-
"""Register tools with the FastMCP app."""
764+
"""@private Register tools with the FastMCP app.
765+
766+
This is an internal function and should not be called directly.
767+
"""
762768
app.tool(list_connector_config_secrets)
763769
for tool in (
764770
describe_default_cache,
@@ -775,5 +781,5 @@ def register_local_ops_tools(app: FastMCP) -> None:
775781
# Register each tool with the FastMCP app.
776782
app.tool(
777783
tool,
778-
description=(tool.__doc__ or "").rstrip() + "\n" + CONFIG_HELP,
784+
description=(tool.__doc__ or "").rstrip() + "\n" + _CONFIG_HELP,
779785
)

airbyte/mcp/server.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,31 @@
77
from fastmcp import FastMCP
88

99
from airbyte._util.meta import set_mcp_mode
10-
from airbyte.mcp._cloud_ops import register_cloud_ops_tools
11-
from airbyte.mcp._connector_registry import register_connector_registry_tools
12-
from airbyte.mcp._local_ops import register_local_ops_tools
1310
from airbyte.mcp._util import initialize_secrets
11+
from airbyte.mcp.cloud_ops import register_cloud_ops_tools
12+
from airbyte.mcp.connector_registry import register_connector_registry_tools
13+
from airbyte.mcp.local_ops import register_local_ops_tools
1414

1515

1616
set_mcp_mode()
1717
initialize_secrets()
1818

1919
app: FastMCP = FastMCP("airbyte-mcp")
20+
"""The Airbyte MCP Server application instance."""
21+
2022
register_connector_registry_tools(app)
2123
register_local_ops_tools(app)
2224
register_cloud_ops_tools(app)
2325

2426

2527
def main() -> None:
26-
"""Main entry point for the MCP server."""
28+
"""@private Main entry point for the MCP server.
29+
30+
This function starts the FastMCP server to handle MCP requests.
31+
32+
It should not be called directly; instead, consult the MCP client documentation
33+
for instructions on how to connect to the server.
34+
"""
2735
print("Starting Airbyte MCP server.", file=sys.stderr)
2836
try:
2937
asyncio.run(app.run_stdio_async())

0 commit comments

Comments
 (0)