Python SDK API reference
Complete reference for the MarcoPolo Python SDK resources, methods, models, and errors.
Preview release
This reference documents the shipped surface of marcopolo-sdk 0.2.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, # any Marcopolo credential; never interpreted client-side
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: client.connections, client.connection_types, client.connection_setup, client.operations, client.catalog, client.workspace.
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(...)
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
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 setup session, no inputs), 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
78 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 |
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 |
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), file-backed fields (satisfied through the Marcopolo app's upload flow), wrong-method submissions, and hosted-OAuth methods with errors naming the problem. Interactive types go through connection setup. 409 when the derived name already exists.
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)
client.connection_setup.start(...)
writeconnection_setup.start(connection_type=, display_name=, return_url=, client_session_id=None, requested_scopes=None) returns ConnectionSetupStart.
Starts a hosted provider authorization for the current end user. Retrying with the same client_session_id reuses the 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 principal may not create connections or the return_url origin is not registered for the namespace; APIError(503) when the provider is not configured on the deployment.
client.connection_setup.get(setup_session_id)
readReturns ConnectionSetupSession. Missing, expired, and another principal's sessions all read as 404.
ConnectionSetupSession
| Field | Type | Notes |
|---|---|---|
setup_session_id | str | Unguessable, principal-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. |
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: the provider URL to open for the end user. Provider tokens never appear in any of these models.
Operations
client.operations.query(...)
writeoperations.query(
connection, *,
query_path=None, query_text=None, provider_operation=None,
parameters=None, input_reference=None,
inline=False, inline_limit=500,
)Returns Operation. Exactly one source. parameters template-substitutes into the query; input_reference chains a prior result reference in as input; provider_operation 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. ResourceGoneError (410) when the relation has been dropped — distinct from 404.
Operation
| 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.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 list[WorkspaceConnection]. Each entry 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.
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, or expired credential. For 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. |
UpstreamTimeoutError | 504 | The execution ceiling was reached; nothing completed. |
APIError | other | Any other server response, including 429 and 5xx, 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.2.0, Python 3.11+. Breaking wire changes before general availability are gated by the version floor rather than silently changing behavior. 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.