Getting StartedPython SDK

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 ValueError locally, before any request leaves the client.
  • Timestamps are timezone-aware datetime objects; enums are typed Literals.

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)

write

Returns 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

FieldTypeNotes
access_tokenstrBearer credential for Marcopolo(access_token=...). Scrubbed from repr().
token_typestr"Bearer"
expires_inintSeconds; fixed at 300. Re-exchange the key rather than refreshing.
email, namespace, tenantstrEchoed so the caller can confirm where the token landed without decoding it.

Connection types

client.connection_types.list(...)

read

connection_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)

read

Returns ConnectionType; 404 for unknown types.

ConnectionType

FieldTypeNotes
connection_typestrStable identifier, e.g. "pg", "hubspot".
display_name, description, categorystr / str? / str?
auth_methodslistWhich creation paths the type supports.
capabilitieslistSetup-time features (test, schema, ssh_tunnel, file handling, …). Runnable operations come from workspace connections.
setup_methodslistThe type's ways of connecting, in recommended order. See SetupMethod below.
setup_schemadictDeprecated in favor of setup_methods: the flat JSON schema for the non-interactive path.
icon_pathstrPublic 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_featuresmodelPresentation hints, including requires_oauth.
deprecatedbool

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:

FieldNotes
choicesSetupFieldChoice value/label pairs for enum inputs.
item_type, min_itemsElement type and minimum length for array fields.
fileA SetupFileSpec (extensions, max_size_mb, allow_create_empty, info_text) for file-backed inputs.
group_labelDisplay heading shared by a dotted group.
advancedRender 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().

TypeProviderCategoryAuth
clickupClickUpanalyticsoauth
freshdeskFreshdeskanalyticsmanual
grafana_lokiGrafana Lokianalyticsmanual
grafana_mimirGrafana Mimiranalyticsmanual
grafana_tempoGrafana Tempoanalyticsmanual
graphiteGraphiteanalyticsmanual
hubspotHubSpotanalyticsoauth
lightfieldLightfieldanalyticsmanual
mixpanelMixpanelanalyticsmanual
netsuiteNetSuiteanalyticsmanual
salesforceSalesforceanalyticsoauth
sentrySentryanalyticsmanual
slackSlackanalyticsmanual + oauth
treasuredataTreasureDataanalyticsmanual
workosWorkOSanalyticsmanual
yandex_appmetrikaYandex AppMetricaanalyticsmanual
yandex_metrikaYandex Metricaanalyticsmanual
cloudwatchAmazon CloudWatchcloudmanual
cloudwatch_insightsAmazon CloudWatch Logs Insightscloudmanual
aws_esAmazon Elasticsearch Servicecloudmanual
athenaAthenacloudmanual
s3AWS S3cloudmanual
abfsAzure Blob Storagecloudmanual
abfssAzure Blob Storage Securecloudmanual
azure_cosmosdbAzure Cosmos DB (SQL API)cloudmanual
bigqueryBigQuerycloudmanual
elasticsearch2ElasticSearchcloudmanual
fabsparkFabric Sparkcloudmanual
elasticsearch2_ImmersaSQLElasticSearchImmersaSQLElasticSearchcloudmanual
deltaMicrosoft Fabric OneLakecloudmanual
elasticsearch2_OpenDistroSQLElasticSearchOpenDistroSQLElasticSearchcloudmanual
sftpSFTPcloudmanual
elasticsearch2_XPackSQLElasticSearchXPackSQLElasticSearchcloudmanual
amazon_documentdbAmazon DocumentDBdatabasemanual
drillApache Drilldatabasemanual
arangodbArangoDBdatabasemanual
axibasetsdAxibase Time Series Databasedatabasemanual
CassandraCassandradatabasemanual
clickhouseClickHousedatabasemanual
cockroachCockroachDBdatabasemanual
dataprimeCoralogixdatabasemanual
couchbaseCouchbasedatabasemanual
dgraphDgraphdatabasemanual
druidDruiddatabasemanual
exasolExasoldatabasemanual
githubGitHubdatabaseoauth
hiveHivedatabasemanual
hive_httpHive (HTTP)databasemanual
impalaImpaladatabasemanual
influxdbInfluxDBdatabasemanual
kylinKylindatabasemanual
memsqlMemSQLdatabasemanual
mssqlMicrosoft SQL Serverdatabasemanual
mongodbMongoDBdatabasemanual
mysqlMySQLdatabasemanual
rds_mysqlMySQL (Amazon RDS)databasemanual
phoenixPhoenixdatabasemanual
pinotPinotdatabasemanual
pgPostgreSQLdatabasemanual
prestoPrestodatabasemanual
promqlPrometheusdatabasemanual
redshiftRedshiftdatabasemanual
redshift_iamRedshift (with IAM User/Role)databasemanual
remote_redashRemoteRedashdatabasemanual
rocksetRocksetdatabasemanual
insecure_scriptScriptdatabasemanual
scyllaScyllaDBdatabasemanual
snowflakeSnowflakedatabasemanual
sqliteSqlitedatabasemanual
trinoTrinodatabasemanual
verticaVerticadatabasemanual
google_driveGoogle Drivedocumentoauth
jiraJiradocumentmanual
jsonJSONdocumentmanual
local_fileLocal Filedocumentmanual
onedriveOneDrivedocumentoauth
sharepointSharePointdocumentoauth
uptycsUptycssecuritymanual

Connections

client.connections.list()

read

Returns list[Connection] — everything visible to the principal.

client.connections.get(connection)

read

Returns Connection. Invisible and missing are both 404.

client.connections.get_configuration(connection)

read

Returns ConnectionConfiguration: provider settings with secret values masked.

client.connections.create(...)

write

connections.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(...)

write

connections.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)

delete

204 on success; requires management permission.

Connection

FieldTypeNotes
namestrStable machine identifier used in every other call.
display_namestrHuman name. Validated after trimming: 3–64 chars, at least one letter or number.
connection_type, connection_type_display_name, categorystr / str / str?
auth_methodliteralmanual | oauth | service_account | builtin
owner, is_owner, can_managestr? / bool / bool
share_modeliteralprivate | company | users
access_reasonliteralWhy the principal can see it: owner | shared_with_company | shared_with_you | admin | unowned
is_personal, is_demo_connectionbool

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)

write

Returns ConnectionSharing. ShareScope.COMPANY, or ShareScope.USERS with a user list.

client.connections.unshare(connection, scope, users=None)

write

Returns ConnectionSharing. Symmetric with share.

client.connections.get_sharing(connection)

read

Returns 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(...)

write

connection_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)

read

Returns ConnectionSetupSession. Missing, expired, and another principal's sessions all read as 404.

ConnectionSetupSession

FieldTypeNotes
setup_session_idstrUnguessable, principal-scoped.
statusliteralpending → exactly one of ready | failed. Terminal states never change.
connection_type, connection_name, display_namestrconnection_name is the name the connection is addressable by once ready.
return_urlstr?Where the user's browser returns in your application.
created_at, expires_atdatetimeSessions expire 15 minutes after their last change.
failuremodel?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(...)

write
operations.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)

read

Returns OperationRecords: a bounded page from a materialized result; limit accepts 1–5000. ResourceGoneError (410) when the relation has been dropped — distinct from 404.

Operation

FieldTypeNotes
idstrIdentifies the run; pass to records().
kindliteral"query"
connection_name, started_at, duration_msstr / datetime / int
statusliteralsucceeded | failed. A query that ran and failed is a completed operation, not an HTTP error.
failuremodel?Category and message when status="failed".
resultResult?Present on success.

Result

FieldTypeNotes
inline_outcomeliteralnot_requested | included | unavailable — a degraded inline read is reported, not returned as an empty success.
referencemodel?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.
recordsmodel?Inline rows when requested: rows, fields, truncation metadata. inline_limit accepts 1–5000.

Catalog

client.catalog.databases(connection)

read

Returns CatalogDatabaseList: top-level containers. ValidationError when the connector publishes no catalog.

client.catalog.tables(connection, database=)

read

Returns CatalogTableList.

client.catalog.columns(connection, database=, table=)

read

Returns CatalogColumnList: column names, source types, descriptions, attributes.

client.catalog.query_guide(connection)

read

Returns 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()

read

Returns 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.

ExceptionStatusMeaning
AuthenticationError401Missing, invalid, or expired credential. For user tokens: re-exchange the namespace key.
PermissionDeniedError403Authenticated but not allowed — policy, ownership, or an unregistered OAuth return origin.
NotFoundError404Missing or not visible to this principal; the two are indistinguishable by design.
ValidationError400 / 422Input the contract rejects.
ConflictError409State conflict, e.g. a connection name that already exists.
ResourceGoneError410Existed and was dropped — e.g. an expired result relation.
SDKVersionUnsupportedError426Package below the service's compatibility floor; upgrade.
UpstreamTimeoutError504The execution ceiling was reached; nothing completed.
APIErrorotherAny other server response, including 429 and 5xx, with retryable derived from status and method safety.
TransportErrorThe request never produced an HTTP response.
ResponseValidationErrorThe 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 echoes X-Marcopolo-Min-SDK-Version.
  • Generated request models reject unknown fields; generated response models ignore unknown additive fields while validating all published fields strictly.
  • max_retries applies to transport-level connection failures. Application-level retries are the caller's decision, guided by error.retryable.
  • Non-loopback base URLs must be HTTPS.
  • Requests may be rate limited; a 429 surfaces as APIError with retryable=True and any server-provided retry_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 — include correlation_id values when reporting issues.
  • Models are regenerated from the service's committed OpenAPI contract on every build, keeping SDK types aligned with the wire.

On this page