{
  "markdown": "# partner-center-mcp\n[![partner-center-mcp MCP server](https://glama.ai/mcp/servers/tunahanaliozturk/partner-center-mcp/badges/card.svg)](https://glama.ai/mcp/servers/tunahanaliozturk/partner-center-mcp)\n\nBuilding against the Partner Center REST API means living in Microsoft Learn. Two hundred odd\nendpoint pages, an archived .NET SDK that still turns up in search results, and error codes that\ntell you almost nothing on their own.\n\nThis MCP server puts that knowledge next to your agent. Ask how to cancel a subscription and you\nget the verified method, path, headers, a working code sample, and the constraints the page\nactually warns about. It holds no credentials and never calls Partner Center. Every answer comes\nfrom a bundled knowledge pack, with a cached Microsoft Learn search as the fallback.\n\n> **Unofficial, community project.** Not affiliated with, sponsored, or endorsed by Microsoft.\n> \"Partner Center\" and \"Microsoft\" are trademarks of Microsoft, used here only descriptively.\n\n## Why\n\nMicrosoft archived the Partner Center .NET SDK (3.4.0) in June 2023 and points partners at the\nREST APIs instead. Plenty of code still hasn't moved. The retired `graph.windows.net` audience\nkeeps producing 401 / `900420`, and from **2026-04-01** App+User API calls enforce MFA.\n\nSo the server does two things. It shows you the current REST and auth patterns, and it explains\nthe errors you hit on the way there.\n\n## How it works\n\nYour MCP host (Claude Code, Cursor, Copilot, VS Code) talks to the server over MCP, on stdio by\ndefault or HTTP if you'd rather. The server reads from a knowledge pack that is zod-validated at\nload and anchored to official Learn pages. When the pack has no answer it falls back to a cached\ndoc search.\n\n![An MCP host talks to partner-center-mcp over stdio or HTTP. The server exposes tools plus resources and prompts, answers from a zod-validated knowledge pack, falls back to a cached Microsoft Learn search, and a weekly CI job checks the pack against the docs.](https://raw.githubusercontent.com/tunahanaliozturk/partner-center-mcp/master/assets/architecture.svg)\n\nA typical call: the agent picks a tool such as `pc_generate_call`, the server looks the scenario up\nin the pack, and back comes the method, path, headers, a ready code sample, and the gotchas, each\ncarrying the `docUrl` it was verified against.\n\n## Run\n\n```bash\nnpx partner-center-mcp\n```\n\nNo configuration, API keys, or network access to Partner Center required.\n\nRequires Node.js 20 or newer. (0.9.0 dropped Node 18, which reached end of life in April 2025.)\n\n## Add to your MCP host\n\nThe server speaks MCP over **stdio**, so any MCP-capable host works. There's nothing\nhost-specific to install. Use whichever config your host expects:\n\n**VS Code** (`.vscode/mcp.json`) and **Visual Studio** (`.mcp.json`):\n\n```json\n{ \"servers\": { \"partner-center\": { \"command\": \"npx\", \"args\": [\"-y\", \"partner-center-mcp\"] } } }\n```\n\n**GitHub Copilot.** Copilot reads the same `.vscode/mcp.json` (VS Code) / `.mcp.json` (Visual\nStudio) shown above; no extra config needed.\n\n**Cursor** (`.cursor/mcp.json`) and **Windsurf** (`~/.codeium/windsurf/mcp_config.json`):\n\n```json\n{ \"mcpServers\": { \"partner-center\": { \"command\": \"npx\", \"args\": [\"-y\", \"partner-center-mcp\"] } } }\n```\n\n**Claude Code:**\n\n```bash\nclaude mcp add partner-center -- npx -y partner-center-mcp\n```\n\n**Claude Desktop** (`claude_desktop_config.json`), **Cline**, and **Zed** use the same\n`mcpServers` shape as Cursor above.\n\n> Tip: also add the **Microsoft Learn MCP server** (`https://learn.microsoft.com/api/mcp`)\n> alongside this one for broad documentation search.\n\n### Remote / HTTP (optional)\n\nPrefer a hosted endpoint over stdio? Run the Streamable HTTP variant:\n\n```bash\nPORT=3000 npx -p partner-center-mcp partner-center-mcp-http\n# MCP endpoint: POST http://localhost:3000/mcp   •   health: GET /healthz\n```\n\n**The endpoint has no authentication of its own**, so it binds `127.0.0.1` by\ndefault. Request bodies are capped at 1 MiB, and a browser `Origin` has to be\nloopback or explicitly allowed, which is what keeps a random web page from\ndriving your local server.\n\n| Variable | Default | What it does |\n| --- | --- | --- |\n| `PORT` | `3000` | Port to listen on. |\n| `HOST` | `127.0.0.1` | Interface to bind. Set `0.0.0.0` only behind a proxy that authenticates. |\n| `ALLOWED_ORIGINS` | none | Comma-separated browser origins allowed in addition to loopback. |\n| `MAX_BODY_BYTES` | `1048576` | Largest accepted request body. |\n\n## Tools\n\n| Tool | Purpose |\n| --- | --- |\n| `pc_list_scenarios` | List supported REST scenarios, optionally filtered by `area`. |\n| `pc_get_scenario` | Full detail for one scenario: method, path, headers, examples, gotchas. |\n| `pc_generate_call` | Emit a current REST call (`curl`/`csharp`/`typescript`/`powershell`) with auth/retry/pagination helpers. Never the archived SDK. |\n| `pc_validate_request` | Lint a REST call (method, URL, headers, auth) against the known scenarios. |\n| `pc_plan_purchase` | The ordered New Commerce purchase workflow: product → SKU availability → cart → checkout → subscriptions. |\n| `pc_migrate_from_sdk` | Translate archived .NET SDK code into the equivalent REST scenario(s). |\n| `pc_auth_guidance` | Current auth guidance for app-only / app+user, per national cloud, with GDAP + MFA notes. |\n| `pc_check_auth` | Lint an auth/client snippet for retired patterns (graph.windows.net, ADAL, archived SDK, AzureAD PS). |\n| `pc_build_request` | Build a ready-to-send request: fills path placeholders, generates `MS-RequestId`/`MS-CorrelationId`, and a body skeleton from the scenario's fields. |\n| `pc_explain_lifecycle` | What you can do to a subscription in its current state: legal operations, the field each precondition reads, and the errors a failed precondition returns. |\n| `pc_plan_subscription_change` | Ordered call sequence for one lifecycle change: seats up/down, upgrade, cancel, renewal changes, suspend, reactivate, migrate, transfer. |\n| `pc_plan_order_lifecycle` | Ordered call sequence from cart to *provisioned* subscriptions, with the cancellation and add-on branches. |\n| `pc_plan_transfer` | Ordered billing-ownership transfer workflow (create → poll → verify). |\n| `pc_plan_gdap_onboarding` | Ordered GDAP onboarding workflow (create → approve → verify) over Microsoft Graph. |\n| `pc_plan_csp_onboarding` | Ordered CSP customer onboarding (account linking): invite → verify relationship → confirm agreement → transact. |\n| `pc_plan_user_onboarding` | Ordered user onboarding: create user → assign licenses → grant roles → verify. |\n| `pc_plan_user_offboarding` | Ordered user offboarding: remove licenses → strip roles → delete user (30-day restore window). |\n| `pc_plan_reconciliation` | Ordered reconciliation workflow (invoice → billed/unbilled line items → statement). |\n| `pc_lookup_error` | Decode an error code: causes, remediation, and the scenarios it commonly hits. |\n| `pc_decode_error` | Paste a raw error response → decoded code, likely scenarios, and the correlation id for support. |\n| `pc_diagnose` | Map a symptom to likely causes, fixes, and relevant scenarios. |\n| `pc_get_enums` | Look up enum values (billingCycle, termDuration, targetView, transitionType, status, …). |\n| `pc_get_resource` | Field dictionary for resources (Customer, Subscription, Order, Invoice, migration schedules, …). |\n| `pc_whats_new` | Deprecations & deadlines (MFA enforcement, graph.windows.net, v1→v2 reconciliation, …). |\n| `pc_plan_prerequisites` | For any scenario, the ordered calls that produce the ids its path needs, and the parameters you supply yourself. |\n| `pc_diff_pack` | What changed between pack releases: scenarios added, removed, or whose route, auth, fields or constraints moved. |\n| `pc_search_docs` | Fetch live Microsoft Learn excerpts. The fallback when the curated pack has no answer. |\n| `pc_get_reference` | Base URLs, headers, versioning, sandbox, rate limits, national-cloud differences. |\n\nEvery tool carries the metadata a calling agent needs: a `title`, a description that says when to\nuse it *and* which sibling to prefer instead, a description on every input parameter, a declared\n`outputSchema`, and MCP behaviour annotations. All 28 are `readOnlyHint: true` and\n`destructiveHint: false`, because the server holds no credentials and calls no Partner Center\nendpoint. It only reads the bundled pack. Three tools break `idempotentHint` or `openWorldHint`:\n`pc_search_docs` and `pc_get_scenario` with `enrich: true` both reach Microsoft Learn, and\n`pc_build_request` mints a fresh `MS-RequestId` on every call.\n\nResponses share one envelope. `{ ok, data }` on success, `{ ok: false, error, suggestions? }` on\nfailure, returned as `structuredContent` and validated against each tool's `outputSchema` by the\nMCP SDK.\n\n## Coverage\n\nScenarios cover:\n\n- **Customers.** Identity and profiles, search, users and directory roles, relationship removal,\n  agreements and consent, self-serve policies.\n- **Subscriptions.** The whole lifecycle: seats up and down, upgrade, cancel, renewal changes,\n  suspend and reactivate, add-ons, New Commerce migration, transfer.\n- **Orders and carts.** Through to provisioning status, not just checkout.\n- **Devices.** Autopilot batches and configuration policies, end to end.\n- **Billing and pricing.** Azure consumption usage at every level, spending budgets and overage,\n  invoices and reconciliation line items, service costs, margins and growth margins, price sheets,\n  the offer matrix, FX rates, and promotion eligibility.\n- **Analytics.** Subscription, indirect reseller, referral and search analytics, plus the three\n  separate licence usage and deployment families.\n- Plus catalog and products, licenses, address and domain validation, audit, support, security and\n  MFA, and partner profiles.\n\nEvery scenario carries the `docUrl` it was verified against and the date it was last checked, and\n185 of them ship the response example their page publishes, so field names and nesting can be read\noff rather than guessed at.\nNational clouds covered: commercial, 21Vianet (China), and US Gov.\n\nLifecycle changes come with their *preconditions*, not just their endpoints. `pc_explain_lifecycle`\nreturns the state machine: which operation is legal from which state, the field to read off the\nlive subscription first (`cancellationAllowedUntilDate`, `autoRenewEnabled`, `suspensionReasons`),\nand the error you get when the precondition fails.\n\nThe pack is also browsable as MCP resources (`pc://scenarios`, `pc://errors`, `pc://auth`,\n`pc://reference`, `pc://sdk-map`, `pc://enums`, `pc://deprecations`, `pc://resources`,\n`pc://lifecycle`, `pc://examples`, `pc://history`, `pc://scenario/{id}`) and three prompts (`migrate-sdk`, `diagnose-issue`,\n`plan-purchase`) for hosts that surface them.\n\nAlongside the scenarios it ships enum values, a resource field dictionary, and a deprecations and\ndeadlines timeline. `npm run export` turns the whole pack into an OpenAPI 3.0 spec and a Postman\ncollection.\n\n## Examples\n\nDecode an error you hit in production:\n\n```jsonc\n// pc_lookup_error { \"code\": \"900420\" }\n{\n  \"httpStatus\": 401,\n  \"errorCode\": \"900420\",\n  \"description\": \"The audience in the token is invalid and is no longer supported in Partner Center API.\",\n  \"causes\": [\"Token requested with the retired graph.windows.net audience\"],\n  \"remediation\": \"Request the token with resource https://api.partnercenter.microsoft.com ...\",\n  \"docUrl\": \"https://learn.microsoft.com/partner-center/developer/deprecate-azure-active-directory-graph-token\"\n}\n```\n\nLint old auth/client code before you ship it:\n\n```jsonc\n// pc_check_auth { \"code\": \"new AuthenticationContext(); get(\\\"https://graph.windows.net\\\"); partner.Customers...\" }\n{\n  \"findings\": [\n    { \"severity\": \"error\",   \"message\": \"Uses the retired graph.windows.net audience; Partner Center returns 401 / 900420.\", \"fix\": \"Request the token with resource https://api.partnercenter.microsoft.com.\" },\n    { \"severity\": \"warning\", \"message\": \"Appears to use ADAL, which is deprecated.\", \"fix\": \"Use MSAL with the secure application model.\" }\n  ],\n  \"clean\": false\n}\n```\n\nCatch a wrong call before you make it:\n\n```jsonc\n// pc_validate_request { \"method\": \"POST\", \"url\": \"/v1/customers/abc/subscriptions\", \"headers\": { \"Authorization\": \"Bearer x\" } }\n{\n  \"ok\": false,\n  \"findings\": [\n    { \"severity\": \"error\", \"message\": \"Path matches a known scenario but the method POST is wrong; expected GET.\",\n      \"fix\": \"Use GET for /v1/customers/{customer-id}/subscriptions.\" }\n  ]\n}\n```\n\n## Develop\n\n```bash\nnpm install\nnpm test\nnpm run build\n```\n\nThe knowledge pack lives in `data/` (date-versioned; each record carries a `docUrl` and\n`lastVerified`). Schemas in [`src/knowledge/schema.ts`](src/knowledge/schema.ts) validate every\nfile at load time, so malformed or drifted data fails fast.\n\nVerification runs in two halves, one offline and one networked.\n\n`npm run check-pack` is the offline half and runs on every PR. It compares each scenario's\n`method`, `path`, and headers against `verification/doc-facts.json`, a committed snapshot of what\nthe Learn pages actually say, and lists documented endpoints that still have no scenario.\n\n`npm run check-docs` is the weekly networked half. It re-fetches every referenced page and diffs it\nagainst the snapshot, keying drift off the source commit each Learn page embeds. It fails on a\ndead, moved, or replaced page, on a page that became unreadable, and when a field the pack depends\non changed. The weekly GitHub Action opens an issue when that happens. An upstream edit that\ntouched only prose is reported without failing the run. `npm run check-docs:update` does the same\nfetch and rewrites the snapshot; `npm run docfacts:refresh` rebuilds it from scratch across the\nwhole `developer/` section of the Learn table of contents.\n\nFor the rest: `npm run eval` runs a deterministic golden-case suite, `npm run eval:llm` (needs\n`ANTHROPIC_API_KEY`) checks that a real model picks the right tool for a question, and\n`npm run export` emits the OpenAPI spec and Postman collection.\n\n`npm run read-doc -- <slug>` prints one Learn page as plain text, which is how new scenarios get\nauthored. `npm run examples:refresh` re-collects the response examples; it merges rather than\noverwrites, so a run that Learn rate-limits cannot lose the previous one's work.\n\nThe .NET server in [`dotnet/`](dotnet/) exposes the same 28 tools from the same `data/` pack and\nships to NuGet as `tunahanaliozturk.PartnerCenterMcp`. `dotnet test PartnerCenterMcp.Tests` runs its\nsuite, one test of which asserts the two servers expose the same tool names.\n\n`npm run pack-diff` reports what changed since the last recorded release, comparing a fingerprint\nof every scenario's route, auth, headers, fields, response shape and gotchas. Re-verifying a\nscenario is deliberately not a change. `npm run pack-diff -- --record X.Y.Z` writes the result into\n`data/history.json`, which is what the `pc_diff_pack` tool serves.\n\n## Contributing\n\nNew scenarios and doc-accuracy fixes are very welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).\nThis is an unofficial, community project and is not affiliated with Microsoft.\n",
  "bytes": 15172,
  "sha": "62cc259adeef7e94e4658809a040d6f4863a892153710a453cff2dd8b83d7e0f",
  "repo_slug": "tunahanaliozturk/partner-center-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_tunahanaliozturk_partner_cente_a00e4a28/readme"
}