Python SDK API reference
Reference for the MarcoPolo Python SDK resources, methods, models, and errors.
Preview release
This reference covers marcopolo-sdk 0.3.0 (Python 3.11+).
New to the SDK? Start with the developer guide.
Conventions
- All methods are async; both clients are async context managers and should be closed (or used with
async with). - Request models reject unknown fields; response models tolerate additive fields while validating all published ones strictly, so old SDKs keep working as the API grows.
- Empty or blank string arguments raise
ValueErrorlocally, before any request leaves the client. - Timestamps are timezone-aware
datetimeobjects; enums are typedLiterals.
Client and authentication
Marcopolo(...)
Marcopolo(
access_token: str, # an API token from Developer Tools, or a namespace user token
base_url: str = "https://mcp.marcopolo.dev",
timeout: float = 60.0,
max_retries: int = 2, # transport-level connection retries
client_name: str | None = None, # User-Agent override
client_version: str | None = None,
)Resources covered here: client.connections, client.connection_types, client.connection_setup, client.operations, client.catalog, client.workspace, and client.toolkit (see Agent toolkit).
Plain-HTTP base URLs are rejected unless loopback, because the bearer credential rides every request. The client sends X-Marcopolo-SDK-Version on every call; see compatibility.
MarcopoloNamespace(...)
For platforms with a namespace provisioned by Marcopolo; most callers authenticate with an API token and don't need it. See MarcoPolo Namespace with Per-User Workspaces.
MarcopoloNamespace(
api_key: str, # namespace key, "mpk_..."
base_url: str = "https://mcp.marcopolo.dev",
timeout: float = 30.0,
)The namespace key is attached only to the token-exchange request, never stored on client headers, and the exchange is never retried automatically.
Namespace user tokens
Only for platforms with a provisioned namespace. See MarcoPolo Namespace with Per-User Workspaces.
MarcopoloNamespace.issue_user_token(email)
writeReturns UserToken. Provisions the user on first issue. The tenant is derived from the email domain server-side. Consumer email domains are refused with ValidationError.
UserToken
| Field | Type | Notes |
|---|---|---|
access_token | str | Bearer credential for Marcopolo(access_token=...). Scrubbed from repr(). |
token_type | str | "Bearer" |
expires_in | int | Seconds; fixed at 300. Re-exchange the key rather than refreshing. |
email, namespace, tenant | str | Echoed so the caller can confirm where the token landed without decoding it. |
Connection types
client.connection_types.list(...)
readconnection_types.list(search=None, category=None, auth_method=None) returns list[ConnectionType]. Filters combine. auth_method is one of manual | oauth | service_account | builtin.
client.connection_types.get(connection_type)
readReturns ConnectionType; 404 for unknown types.
ConnectionType
| Field | Type | Notes |
|---|---|---|
connection_type | str | Stable identifier, e.g. "pg", "hubspot". |
display_name, description, category | str / str? / str? | |
auth_methods | list | Which creation paths the type supports. |
capabilities | list | Setup-time features (test, schema, ssh_tunnel, file handling, …). Runnable operations come from workspace connections. |
setup_methods | list | The type's ways of connecting, in recommended order. See SetupMethod below. |
setup_schema | dict | Deprecated in favor of setup_methods: the flat JSON schema for the non-interactive path. |
icon_path | str | Public logo path, e.g. /app/static/db-logos/pg.png — join onto the service base URL; served unauthenticated, with default.png available as a fallback. |
ui_features | model | Presentation hints, including requires_oauth. |
deprecated | bool |
SetupMethod and SetupField
Each SetupMethod carries method (stable id), kind (fields: collect the listed inputs and call create; hosted_oauth: start a hosted setup session), category, display_name, description, and fields.
Each SetupField carries name (dotted for nested groups, e.g. ssh_tunnel.ssh_pkey), type, required, secret, label, description, default, plus everything a form renderer needs:
| Field | Notes |
|---|---|
choices | SetupFieldChoice value/label pairs for enum inputs. |
item_type, min_items | Element type and minimum length for array fields. |
file | A SetupFileSpec (extensions, max_size_mb, allow_create_empty, info_text) for file-backed inputs. |
group_label | Display heading shared by a dotted group. |
advanced | Render collapsed by default. |
Supported connection types
79 connection types ship in this preview. This table is generated from the authoritative registry; discover the live set (and each type's setup methods) at runtime through connection_types.list().
| Type | Provider | Category | Auth |
|---|---|---|---|
clickup | ClickUp | analytics | oauth |
freshdesk | Freshdesk | analytics | manual |
grafana_loki | Grafana Loki | analytics | manual |
grafana_mimir | Grafana Mimir | analytics | manual |
grafana_tempo | Grafana Tempo | analytics | manual |
graphite | Graphite | analytics | manual |
hubspot | HubSpot | analytics | oauth |
lightfield | Lightfield | analytics | manual |
mixpanel | Mixpanel | analytics | manual |
netsuite | NetSuite | analytics | manual |
quickbooks | QuickBooks | analytics | oauth |
salesforce | Salesforce | analytics | oauth |
sentry | Sentry | analytics | manual |
slack | Slack | analytics | manual + oauth |
treasuredata | TreasureData | analytics | manual |
workos | WorkOS | analytics | manual |
yandex_appmetrika | Yandex AppMetrica | analytics | manual |
yandex_metrika | Yandex Metrica | analytics | manual |
cloudwatch | Amazon CloudWatch | cloud | manual |
cloudwatch_insights | Amazon CloudWatch Logs Insights | cloud | manual |
aws_es | Amazon Elasticsearch Service | cloud | manual |
athena | Athena | cloud | manual |
s3 | AWS S3 | cloud | manual |
abfs | Azure Blob Storage | cloud | manual |
abfss | Azure Blob Storage Secure | cloud | manual |
azure_cosmosdb | Azure Cosmos DB (SQL API) | cloud | manual |
bigquery | BigQuery | cloud | manual |
elasticsearch2 | ElasticSearch | cloud | manual |
fabspark | Fabric Spark | cloud | manual |
elasticsearch2_ImmersaSQLElasticSearch | ImmersaSQLElasticSearch | cloud | manual |
delta | Microsoft Fabric OneLake | cloud | manual |
elasticsearch2_OpenDistroSQLElasticSearch | OpenDistroSQLElasticSearch | cloud | manual |
sftp | SFTP | cloud | manual |
elasticsearch2_XPackSQLElasticSearch | XPackSQLElasticSearch | cloud | manual |
amazon_documentdb | Amazon DocumentDB | database | manual |
drill | Apache Drill | database | manual |
arangodb | ArangoDB | database | manual |
axibasetsd | Axibase Time Series Database | database | manual |
Cassandra | Cassandra | database | manual |
clickhouse | ClickHouse | database | manual |
cockroach | CockroachDB | database | manual |
dataprime | Coralogix | database | manual |
couchbase | Couchbase | database | manual |
dgraph | Dgraph | database | manual |
druid | Druid | database | manual |
exasol | Exasol | database | manual |
github | GitHub | database | oauth |
hive | Hive | database | manual |
hive_http | Hive (HTTP) | database | manual |
impala | Impala | database | manual |
influxdb | InfluxDB | database | manual |
kylin | Kylin | database | manual |
memsql | MemSQL | database | manual |
mssql | Microsoft SQL Server | database | manual |
mongodb | MongoDB | database | manual |
mysql | MySQL | database | manual |
rds_mysql | MySQL (Amazon RDS) | database | manual |
phoenix | Phoenix | database | manual |
pinot | Pinot | database | manual |
pg | PostgreSQL | database | manual |
presto | Presto | database | manual |
promql | Prometheus | database | manual |
redshift | Redshift | database | manual |
redshift_iam | Redshift (with IAM User/Role) | database | manual |
remote_redash | RemoteRedash | database | manual |
rockset | Rockset | database | manual |
insecure_script | Script | database | manual |
scylla | ScyllaDB | database | manual |
snowflake | Snowflake | database | manual |
sqlite | Sqlite | database | manual |
trino | Trino | database | manual |
vertica | Vertica | database | manual |
google_drive | Google Drive | document | oauth + service_account |
jira | Jira | document | manual |
json | JSON | document | manual |
local_file | Local File | document | manual |
onedrive | OneDrive | document | oauth |
sharepoint | SharePoint | document | oauth |
uptycs | Uptycs | security | manual |
Connections
client.connections.list()
readReturns list[Connection] — everything visible to the principal.
client.connections.get(connection)
readReturns Connection. Invisible and missing are both 404.
client.connections.get_configuration(connection)
readReturns ConnectionConfiguration: provider settings with secret values masked.
client.connections.create(...)
writeconnections.create(connection_type=, display_name=, setup_method=, fields=) returns Connection.
Non-interactive creation: declare a method from the type's setup_methods and pass its inputs as one fields mapping — the server stores values by the method definition and rejects unknown fields, missing required fields, badly shaped values (wrong type, arrays below min_items), wrong-method submissions, and hosted-OAuth methods with errors naming the problem. Use hosted connection setup for OAuth methods, or authorize them in the web app. 409 when the derived name already exists.
FileUpload
FileUpload.from_path(path)
FileUpload.from_bytes(filename, content)
FileUpload.create_empty() # only where the field's file spec sets allow_create_emptyThe value for a file-backed setup field (one whose SetupField.file spec is set). Serialized as {"filename", "content_base64"} or {"create_empty": true}; the server validates the extension and decoded size against the published spec. A server-side path is never accepted.
client.connections.update(...)
writeconnections.update(connection, display_name=None, configuration_patch=None) returns Connection. Patches metadata and non-secret configuration; at least one field required.
client.connections.test(connection)
Returns ConnectionTest. Runs the provider check through the runtime. A failed check is a returned outcome, not an exception.
client.connections.delete(connection)
delete204 on success; requires management permission.
Connection
| Field | Type | Notes |
|---|---|---|
name | str | Stable machine identifier used in every other call. |
display_name | str | Human name. Validated after trimming: 3–64 chars, at least one letter or number. |
connection_type, connection_type_display_name, category | str / str / str? | |
auth_method | literal | manual | oauth | service_account | builtin |
owner, is_owner, can_manage | str? / bool / bool | |
share_mode | literal | private | company | users |
access_reason | literal | Why the principal can see it: owner | shared_with_company | shared_with_you | admin | unowned |
is_personal, is_demo_connection | bool |
ConnectionTest
connection_name, connection_type, status (succeeded | failed), message, checked_at, latency_ms, and optional authorization_status (valid | reauthorization_required | check_failed) — the signal to send a user back through OAuth setup.
Connection sharing
client.connections.share(connection, scope, users=None)
writeReturns ConnectionSharing. ShareScope.COMPANY, or ShareScope.USERS with a user list.
client.connections.unshare(connection, scope, users=None)
writeReturns ConnectionSharing. Symmetric with share.
client.connections.get_sharing(connection)
readReturns ConnectionSharing: shared_with_company, shared_with_users, optional warning.
Share targets must be members of the tenant. Sharing requires management permission on the connection.
Connection setup (hosted OAuth)
These SDK methods use the REST endpoints POST /api/v1/connection-setup-sessions and GET /api/v1/connection-setup-sessions/{setup_session_id}. They start and observe a browser authorization flow for the current user. They are separate from MarcoPolo's MCP tool surface.
client.connection_setup.start(...)
writeconnection_setup.start(connection_type=, display_name=, return_url=None, client_session_id=None, requested_scopes=None) returns ConnectionSetupStart.
Without return_url, the provider returns the user to MarcoPolo's completion page. With a dedicated MarcoPolo namespace, return_url can point to your application on an origin registered for that namespace; Google Drive does not support this return path.
Retrying with the same client_session_id reuses an in-flight session instead of creating a duplicate.
Errors: ValidationError for an unknown or non-OAuth type or an unusable return_url; PermissionDeniedError when the caller may not create connections or the return origin is not registered; ServiceUnavailableError (503) when the provider is not configured on the deployment.
client.connection_setup.get(setup_session_id)
readReturns ConnectionSetupSession. Missing, expired, and another user's sessions all read as 404.
ConnectionSetupSession
| Field | Type | Notes |
|---|---|---|
setup_session_id | str | Unguessable, user-scoped. |
status | literal | pending → exactly one of ready | failed. Terminal states never change. |
connection_type, connection_name, display_name | str | connection_name is the name the connection is addressable by once ready. |
return_url | str? | Where the user's browser returns in your application, when one was given. |
created_at, expires_at | datetime | Sessions expire 15 minutes after their last change. |
failure | model? | code and message, set only on failed. |
ConnectionSetupStart extends the session with authorization_url, which you open for the user. Provider tokens never appear in these models. See the SDK walkthrough.
Operations
client.operations.query(...)
writeoperations.query(
connection_name, *,
source,
parameters=None, input_reference=None,
inline=False, inline_limit=500,
)Returns Operation. source names exactly one kind:
source | Runs |
|---|---|
{"kind": "query_text", "text": "..."} | Query text supplied with the request. |
{"kind": "saved_query", "path": "..."} | A query file in the user's workspace, by workspace-relative path. Absolute paths and parent traversal are rejected. |
{"kind": "provider_operation", "definition": {...}} | A provider action expressed as configuration rather than query text. |
parameters template-substitutes into the query; input_reference chains a prior result reference in as input; a provider operation's definition is passed to the connector verbatim, in the shape its query guide documents. Synchronous: dispatched, executed, and returned terminal in one call; the execution ceiling is 300 seconds, beyond which UpstreamTimeoutError (504) is raised and nothing has completed. Raise the client timeout above the ceiling for long queries.
client.operations.records(operation_id, limit=500, offset=0)
readReturns OperationRecords: a bounded page from a materialized result; limit accepts 1–5000. Continue with next_offset while it is not None. ResourceGoneError (410) when the relation has been dropped — distinct from 404.
offset = 0
while offset is not None:
page = await client.operations.records(operation_id, limit=500, offset=offset)
consume(page.rows)
offset = page.next_offsetOperation
| Field | Type | Notes |
|---|---|---|
id | str | Identifies the run; pass to records(). |
kind | literal | "query" |
connection_name, started_at, duration_ms | str / datetime / int | |
status | literal | succeeded | failed. A query that ran and failed is a completed operation, not an HTTP error. |
failure | model? | Category and message when status="failed". |
result | Result? | Present on success. |
Result
| Field | Type | Notes |
|---|---|---|
inline_outcome | literal | not_requested | included | unavailable — a degraded inline read is reported, not returned as an empty success. |
reference | model? | name (addressable as a relation in queries against the reserved DUCKDB connection), row_count, and fields — each with name and type. References live in the caller's workspace result store and are not durable storage; a dropped reference reads as 410. |
records | model? | Inline rows when requested: rows, fields, truncation metadata. inline_limit accepts 1–5000. |
Catalog
client.catalog.inspect(connection, database=None, table=None)
readReads the requested depth in one call: databases with only connection, tables with database, and columns with both database and table. Returns the matching list model below. table without database raises ValueError.
client.catalog.databases(connection)
readReturns CatalogDatabaseList: top-level containers. ValidationError when the connector publishes no catalog.
client.catalog.tables(connection, database=)
readReturns CatalogTableList.
client.catalog.columns(connection, database=, table=)
readReturns CatalogColumnList: column names, source types, descriptions, attributes.
client.catalog.query_guide(connection)
readReturns QueryGuide: connection_name and markdown — connector-authored prose describing the provider's query syntax and provider_operation shapes. 404 when the connector publishes none.
Catalog reads authorize through the same rule as running an operation, so a connection you can describe is a connection you can query.
Workspace
client.workspace.connections()
readReturns WorkspaceConnectionListResponse: connections, count, customer, and next_actions. Each entry in connections pairs a Connection with the operations it can actually run (capabilities, e.g. query, test, describe) plus workspace_path and an optional note. Slower than connections.list() because it consults the execution workspace.
client.workspace.shell(command, *, timeout=30)
writeReturns WorkspaceShellResult. Runs a command in the user's persistent workspace and waits up to timeout seconds (1–300). A command that outlives timeout keeps running and returns status="running"; poll it with workspace.shell(f"execution status {result.execution_id}"), whose stdout is the polled execution's record as JSON (status, failure, and an outcome with exit_code, stdout_tail, stderr_tail). A workspace permits one background command at a time. A command that ran and failed returns status="failed"; only a command that never ran raises.
WorkspaceShellResult
| Field | Type | Notes |
|---|---|---|
execution_id | str | Stable id used by execution status. |
status | literal | running | succeeded | failed |
exit_code | int? | None while running. |
stdout, stderr | str | Bounded output tails. |
failure | model? | kind (timed_out | lost | command_failed) and message. |
next_actions | list[str] | Polling or inspection guidance when needed. |
Agent toolkit
client.toolkit.tools()
readReturns list[ToolDefinition]: name, description, input_schema, and result_schema (JSON Schema) for each agent tool. The catalog is bundled with the SDK release, so this makes no network request. Argument and result schemas are derived from the public API contract.
client.toolkit.execute(name, arguments=None)
Invokes the SDK resource method bound to name and returns its ordinary typed result or raises its ordinary error. An unknown name raises ValueError. Common data workflow tools include:
| Tool | Calls |
|---|---|
connections_list | workspace.connections() |
workspace_shell | workspace.shell(command, timeout=) |
connection_catalog | catalog.inspect(connection, database=, table=) |
query_guide | catalog.query_guide(connection) |
operation_records | operations.records(operation_id, limit=, offset=) |
marcopolo.toolkit.langchain.langchain_tools(toolkit)
Returns list[StructuredTool]: asynchronous LangChain tools, usable directly by LangGraph's ToolNode and create_react_agent. Requires the langchain extra (pip install "marcopolo-sdk[langchain]", langchain-core>=0.3.79,<2).
- Arguments are validated against each tool's published input schema before the call.
- Results are returned as JSON message content, with the same data as the
ToolMessageartifact. - Failed executions and recoverable request errors become error
ToolMessages the model can act on; a running shell execution keeps itsexecution_idandnext_actions. AuthenticationError,SDKVersionUnsupportedError,TransportError, andResponseValidationErrorraise to application code.
Error contract
All exceptions derive from MarcopoloError and carry message, code, status_code, retryable, correlation_id, details, and retry_after. The correlation id ties a failure to Marcopolo's server-side traces — include it in support requests.
| Exception | Status | Meaning |
|---|---|---|
AuthenticationError | 401 | Missing, invalid, expired, or revoked credential. Create a new API token; for namespace user tokens, re-exchange the namespace key. |
PermissionDeniedError | 403 | Authenticated but not allowed — policy, ownership, or an unregistered OAuth return origin. |
NotFoundError | 404 | Missing or not visible to this principal; the two are indistinguishable by design. |
ValidationError | 400 / 422 | Input the contract rejects. |
ConflictError | 409 | State conflict, e.g. a connection name that already exists. |
ResourceGoneError | 410 | Existed and was dropped — e.g. an expired result relation. |
SDKVersionUnsupportedError | 426 | Package below the service's compatibility floor; upgrade. |
ServiceUnavailableError | 503 | The workspace or another required service is temporarily unavailable. |
UpstreamTimeoutError | 504 | The execution ceiling was reached; nothing completed. |
APIError | other | Any other server response, including 429 and unclassified 5xx responses, with retryable derived from status and method safety. |
TransportError | — | The request never produced an HTTP response. |
ResponseValidationError | — | The response did not match the published contract; carries the correlation id for reporting. |
Compatibility and transport
- The client sends its immutable package version in
X-Marcopolo-SDK-Version; the service rejects versions below its floor with 426 and always echoesX-Marcopolo-Min-SDK-Version. - Generated request models reject unknown fields; generated response models ignore unknown additive fields while validating all published fields strictly.
max_retriesapplies to transport-level connection failures. Application-level retries are the caller's decision, guided byerror.retryable.- Non-loopback base URLs must be HTTPS.
- Requests may be rate limited; a 429 surfaces as
APIErrorwithretryable=Trueand any server-providedretry_after. - Preview terms: current package version
0.3.0, Python 3.11+. Breaking wire changes before general availability are gated by the version floor rather than silently changing behavior. API tokens are created in Developer Tools; namespace keys, OAuth return-origin registration, and provider enablement are provisioned by your Marcopolo account team, which is also the support channel — includecorrelation_idvalues when reporting issues. - Models are regenerated from the service's committed OpenAPI contract on every build, keeping SDK types aligned with the wire.