Skip to main content
Glama
org-spec
by org-spec

orgspec-mcp

npm package orgspec — the reference MCP server for the Org Context Spec v0.2. Serves an org-context/ repository to any MCP-capable AI agent, and lets agents propose changes that a human approves.

Status: v0.3, in pilot use. Two storage backends: a local folder, or a GitHub repository reached through the REST API (no local clone, no git binary — in propose mode every change becomes a pull request). Two transports: stdio (local) and streamable HTTP (one Node process to self-host, or Netlify). An Azure DevOps backend is planned.

Tools

Two tools — read and propose:

Tool

Purpose

get_context

The context README (reading order, writing rules) + file list + gaps, or any single file; empty repos get onboarding instructions, missing files their starter template

propose_context_change

One coherent change — one or several files, one commit, one pull request for review

search, fetch

Compatibility views over the same files, in the shape ChatGPT connectors require

Related MCP server: AI Knowledge Center MCP

Audit

Reproducible checks that point at what the context does not say yet: files the reading order does not reach, template placeholders never replaced, TODO items, owners left as TODO, effect goals without baseline, target or horizon, horizons that have passed with no outcome recorded, statements the authors themselves marked as unverified, and questions waiting for a decision. It reads only conventions the spec already has — no new syntax.

Findings are signals, never grades: no score, nothing blocks a merge. Same files in, same findings out, wherever it runs:

  • get_context without arguments appends the top findings, so an agent can raise the ones that matter to its task (and propose a fix through the normal review loop — never fill gaps unprompted).

  • npx orgspec audit [dir] [--json] prints the full report for a local folder — for the terminal or a CI step. Exit code is always 0.

  • The web view has an Audit page per repository.

Usage

Local folder (a git clone — commits stay local):

npx orgspec --context /path/to/org-context

GitHub repository (reads and writes via the REST API — nothing to install or clone, works for teammates without git):

GITHUB_TOKEN=ghp_... npx orgspec --github owner/repo --write-mode propose

Options:

  • --context <path> (or ORG_CONTEXT_PATH) — local context repository root. Default: current directory.

  • --github <owner/repo> (or ORG_CONTEXT_GITHUB) — serve a GitHub repository instead of a local folder. Requires a token in ORG_CONTEXT_GITHUB_TOKEN or GITHUB_TOKEN with contents (and, for propose mode, pull request) permission on that repository.

  • --branch <name> (or ORG_CONTEXT_BRANCH) — branch to serve in GitHub mode. Default: the repository's default branch.

  • --write-mode direct|propose (or ORG_CONTEXT_WRITE_MODE) — direct commits approved changes on the current/default branch; propose puts each change on a new context/... branch — in GitHub mode it also opens a pull request for human review. Default: direct for a local folder (your own clone), propose for a GitHub repository (shared — a person reviews).

What the server reads and writes: markdown files (.md) outside hidden paths, and proposals only inside the spec's structure — README.md, organisation/, products/, teams/, method/, system/. Other repository files (tool configuration, workflows, agent instruction files) are neither served nor writable through the tools.

Client configuration (Claude Desktop, Claude Code, VS Code, Cursor, …):

{
  "mcpServers": {
    "org-context": {
      "command": "npx",
      "args": ["-y", "orgspec", "--context", "/path/to/org-context"]
    }
  }
}

Hosted mode (HTTP)

For teams that accept context passing through a hosted server (the same trust model as Jira Cloud or Notion). The server reads and writes the context repo via the GitHub API. Two ways to connect:

Instead of pasting a token, the user installs a GitHub App on the context repo and gets a ready command from /setup (and again, any time, from the repository's Connect page when signed in). The server is named after the repository, org-context-<repo>, so several contexts can sit side by side and both agent and human see which organisation a tool belongs to. The server issues a key per repo (oc1.<installation>.<mac>, an HMAC the server verifies statelessly) and resolves it to a short-lived installation token on each request — nothing is stored. Revoke by uninstalling the App; rotate the private key to invalidate every key at once.

Register the App once (GitHub → Settings → Developer settings → GitHub Apps):

  • Callback URL: https://<your host>/setup, and tick Request user authorization (OAuth) during installation — that is how /setup knows who installed. Also tick Redirect on update so reconfiguring lands there too.

  • Repository permissions: Contents read and write, Pull requests read and write. No webhook needed (untick Active).

  • Where can this App be installed: any account.

  • Generate a private key and note the App ID, Client ID, and a client secret.

Then set on the server: ORG_CONTEXT_APP_ID, ORG_CONTEXT_APP_PRIVATE_KEY (the PEM; a single line with literal \n is accepted), ORG_CONTEXT_APP_CLIENT_ID, ORG_CONTEXT_APP_CLIENT_SECRET. Without them the App path is simply off and /setup answers 404.

ChatGPT, claude.ai, Gemini, Copilot — OAuth

Clients that cannot send custom headers use standard MCP authorization (OAuth 2.1 with PKCE, dynamic client registration, RFC 9728 discovery). Add the MCP URL as a connector; the client discovers /.well-known/oauth-protected-resource on the MCP host, sends the user to sign in with GitHub via the App, and a consent page asks which installed context repo to expose. The token it receives is the same per-repo key with the repo embedded (oc2.…) — still stateless, nothing stored. Registered clients, pending sign-ins and authorization codes are all sealed, self-expiring blobs that travel through the client.

Requires the GitHub App above plus a second callback URL on it: https://<app host>/oauth/callback. The MCP host and the app host must be siblings (mcp. / app.), or set ORG_CONTEXT_APP_ORIGIN explicitly.

ChatGPT's connectors also require tools named search and fetch; the server exposes both as thin views over the same files.

Bring your own repo (multi-tenant, stateless)

Any client can point a running server at its own context repo — the MCP configuration is the whole onboarding. The client sends its repo and its own GitHub token in headers; the token doubles as the access key, and the server stores nothing:

claude mcp add --transport http org-context https://<site>/mcp \
  --header "Authorization: Bearer <fine-grained GitHub token>" \
  --header "X-Org-Context-Repo: owner/org-context"

Optional header: X-Org-Context-Branch: <branch> (default: the repo's default branch). Writes are always proposals — every change becomes a pull request for human review.

The token: a fine-grained token with Repository access: only the context repo (so the blast radius is that repo alone) and repository permissions Contents: read and write plus Pull requests: read and write. Both are needed — with Contents alone, a proposal is committed to a branch but the pull request fails with 403. The token passes through the server on every request but is never stored or logged; if that trust model does not fit, self-host — see below.

Default repo (single-tenant)

Requests without X-Org-Context-Repo are served from a repo configured on the server, gated by a shared access key.

Run anywhere with Node:

ORG_CONTEXT_GITHUB=owner/repo ORG_CONTEXT_GITHUB_TOKEN=github_pat_... \
MCP_ACCESS_KEY=some-long-random-string npm run start:http

With a default repo configured the server refuses to start without MCP_ACCESS_KEY; set ORG_CONTEXT_ALLOW_OPEN=1 to run it open on a local machine. Open mode binds to 127.0.0.1 only, so nothing on the network can reach it; with a key the server listens on every interface. ORG_CONTEXT_HOST overrides the bind address in either mode.

Deploy to Netlify (git-linked — every push deploys):

  1. Push this repository to GitHub and link it to a Netlify site (Site configuration → Build & deploy → Link repository). netlify.toml holds the build settings; Netlify bundles netlify/functions/mcp.mts itself.

  2. Bring-your-own-repo mode works with no configuration at all. To also serve a default repo, add environment variables ORG_CONTEXT_GITHUB, ORG_CONTEXT_GITHUB_TOKEN (a fine-grained token limited to the context repo: contents + pull requests, read/write) and MCP_ACCESS_KEY (any long random string) — then trigger a redeploy so they take effect.

Connect from Claude Code:

claude mcp add --transport http org-context https://mcp.orgspec.org \
  --header "Authorization: Bearer <access key>"
# self-hosted copies serve the endpoint at https://<site>.netlify.app/mcp

Notes: the server is stateless (works on serverless); writes default to propose mode — every change becomes a pull request in the context repo. All context passes through the host in plaintext during processing; use a fine-grained token so the blast radius is the context repo alone.

The write rule

propose_context_change embeds the spec's writing rule: the model recommends, a human decides. The tool instructs agents to show the exact change and get explicit approval before calling. In a git repository every approved change becomes a commit — reviewable, diffable, revertable.

Self-hosting with the package

The npm package is the same code the hosted service runs. orgspec serve starts the HTTP server (MCP endpoint, web view, /setup and OAuth when a GitHub App is configured) as one Node process:

MCP_ACCESS_KEY=<long random string> ORG_CONTEXT_GITHUB=owner/repo \
  ORG_CONTEXT_GITHUB_TOKEN=github_pat_... npx orgspec serve

The process stores nothing and needs no outbound access beyond the GitHub API. Environment variables are listed at the top of src/http.ts.

The two keys

Both keys are values you invent — long random strings, generated for example with openssl rand -base64 24 | tr -d '/+='. Nothing is fetched or registered anywhere.

  • MCP_ACCESS_KEY admits MCP clients on /mcp (sent as the Bearer key).

  • ORG_CONTEXT_WEB_KEY turns on the read-only web view at /c/<that key>/ — a capability link: whoever has the link can read, nobody else. Without the variable there is no web view at all.

Share the link where the audience already is (intranet, team channel). To revoke, restart with a new value; the old link stops working immediately. On an internal network the link is reachable only from inside, which is a second lock on top of the key.

On your own machine, from a local clone

The zero-configuration path — no token, no App, no proxy exception, and it works the same against GitHub.com, GitHub Enterprise Server or any other git host, because the server never talks to an API. Use it for a personal setup or a first pilot inside an organisation:

git clone <the context repository> ~/org-context
claude mcp add org-context -s user -- npx -y orgspec --context ~/org-context

Other MCP clients get the same stdio command. Approved changes become commits in the clone (--write-mode propose puts them on a context/... branch instead); push and open pull requests with git as usual.

The web view over the same clone, visible only to you:

ORG_CONTEXT_PATH=~/org-context ORG_CONTEXT_ALLOW_OPEN=1 \
  ORG_CONTEXT_WEB_KEY=<key> PORT=3456 npx orgspec serve
# → http://localhost:3456/c/<key>/  (audit at /c/<key>/audit)

ORG_CONTEXT_ALLOW_OPEN=1 skips the MCP access key. The server then binds to the loopback interface only, so nothing else on the network can reach it — with a key it listens on every interface (ORG_CONTEXT_HOST overrides both). Switch to ORG_CONTEXT_GITHUB + a fine-grained token when several people should reach one server without a clone, or when proposals should open pull requests by themselves.

On your own machine, without a clone — GitHub CLI

If GitHub CLI (gh) is installed and signed in to the account that can see the context repository, its login doubles as the token: no clone, no token file, and proposals open pull requests by themselves.

gh auth login                                   # once; pick the GitHub host your organisation uses
gh api repos/<owner>/<repo>/contents --jq length  # a number means the server will reach it too

Then register the server with the token resolved at start:

claude mcp add-json org-context -s user '{"type":"stdio","command":"/bin/sh",
  "args":["-c","GITHUB_TOKEN=$(gh auth token) exec npx -y orgspec --github <owner>/<repo>"]}'

Other clients get the same /bin/sh -c … command. The web view works the same way, with ORG_CONTEXT_GITHUB=<owner>/<repo> instead of ORG_CONTEXT_PATH. A signed-in browser is not enough — the server needs a token, and gh is what holds one.

Development

npm install
npm run build   # tsc → dist/
npm test        # type-checks src/ + test/, runs the suite (node:test, no extra deps)

The suite needs no network and no secrets: it generates its own App key material and stubs GitHub. It covers the security-critical paths — key issuing and verification, sealed state, the OAuth/PKCE flow, the /setup authorisation, path validation, the Markdown renderer, the security headers — and runs the Node server black-box. npm test is also Netlify's build command, so a red test blocks the deploy; .github/workflows/ci.yml runs the same on pull requests.

Before a release, npm run pack:smoke packs the tarball, installs it into a scratch prefix and runs both binaries — what CI does in the pack job. To try the unpublished package in a client, point it at the tarball:

npm pack                                  # → orgspec-<version>.tgz
npx --yes --package ./orgspec-<version>.tgz orgspec --context /path/to/org-context

Releases

The hosted service follows main; the npm package follows v* tags, see CHANGELOG.md. npm version minor|patch bumps, commits and tags; git push --follow-tags lets .github/workflows/release.yml stage the version on npm through trusted publishing (no token secret). Nothing goes live until a maintainer approves it — npm stage approve <stage-id> with 2FA, or on npmjs.com. CI proposes, a human decides.

License

MIT

Available Tools

4 tools
fetchA
Read-onlyIdempotent

Read one organizational context file by id (its path, as returned by search).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesFile path, e.g. 'organisation/constraints.md'

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotent, and non-destructive behavior. The description adds the resource type and id provenance (as returned by search), which is useful, but no further behavioral detail is provided.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with zero waste. It conveys exactly what the tool does without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter read tool with annotations carrying the safety profile, the description provides the essential id semantics. It does not explicitly state the return content, but that is reasonably implied by 'Read'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the schema already documents the id as a file path. The description adds extra meaning by specifying the id must come from search, which is beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Read') and resource ('one organizational context file'), plus the id is a path from search. It does not explicitly contrast with sibling 'get_context', so it lacks full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies the tool should be used after search returns a path, but does not mention when not to use it or how it differs from alternatives like get_context. The usage context is present but not explicit enough for a 4.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_contextA
Read-onlyIdempotent

Read the organizational context (Org Context Spec repo). Without arguments: returns the context README (the reading order and writing rules — always start here) plus a list of all context files — or, for a new/empty repository, onboarding instructions for seeding it. With a path: returns that file, or its starter template if the file does not exist yet. Read the relevant context BEFORE writing code, stories, or product documents. If you know which team you work for, read teams/.md early — it maps the team's tracker, systems, and product areas.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoRelative path to a context file, e.g. 'products/parking/product.md'. Omit for the README + file list.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly=true, idempotent=true, and destructive=false, but the description adds substantial non-obvious behavior: the default returns the README plus a file list or onboarding instructions for an empty repo, and a path returns the file or a starter template if missing. This significantly expands what the agent knows beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences long with no fluff, covering invocation modes, return behavior, empty-repo handling, and usage timing. The core 'always start here' guidance is front-loaded, and each sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully documents both call patterns, their return contents, the empty-repository case, and team-specific guidance. Since there is no output schema, this description serves as the sole source of return-value documentation and is complete for a tool of this low complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 100% for the single optional 'path' parameter, the baseline is 3. The description adds extra meaning by stating that a non-existent path triggers a starter template, which the schema does not mention, and clarifies that omitting the argument yields the README and file list.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Read') and resource ('organizational context (Org Context Spec repo)'), and clearly documents both invocation modes (no args vs with a path). This makes it easy to distinguish from propose_context_change (write), search (query), and fetch (generic retrieval) without inspecting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit direction to 'Read the relevant context BEFORE writing code, stories, or product documents' and advises reading teams/<team>.md early when the team is known, giving clear when-to-use context. It doesn't explicitly name alternatives or exclusions, so it falls short of a full when/when-not statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

propose_context_changeA

Propose one coherent change to the context — one or several files that together make up a single logical decision. Bundle everything that belongs together into ONE call: one proposal becomes one commit (and one pull request for review), never one per file. IMPORTANT: the model recommends, a human decides — show the user exactly what will change and get their explicit approval BEFORE calling this tool. Provide the complete new content of each file.

ParametersJSON Schema
NameRequiredDescriptionDefault
changesYesThe file changes making up this ONE proposal — all files that belong to the same decision.
summaryYesOne-line summary of the decision, used as the commit message and pull request title. E.g. 'Update parking effect goal target to 4 min and the actor assumption it rests on'.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are sparse (readOnlyHint=false, destructiveHint=false, etc.) and don't convey the key behavioral trait: this tool creates a commit/PR and requires human approval. The description discloses this workflow clearly. It could add more about side effects (e.g., what happens after approval), but the core behavioral context is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-organized, front-loading the core concept (one coherent change) and then adding the approval workflow. The IMPORTANT callout is effective. Slightly verbose but every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 2 required params, 100% schema coverage, and no output schema, the description covers the essential context: what to bundle, how to get approval, and what to provide. It doesn't explain the return value or post-call behavior, but with no output schema and clear annotations, this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters well. The description adds value by explaining the semantic relationship between parameters: changes must form ONE coherent proposal, and summary becomes the commit message/PR title. This goes beyond the schema's individual field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: propose one coherent change to the context, bundling multiple files into a single logical decision. It distinguishes itself from siblings by emphasizing the proposal/commit/PR workflow, which is unique among get_context, search, and fetch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool: bundle everything that belongs together into ONE call, and never one per file. It also provides critical usage guidance: show the user exactly what will change and get explicit approval BEFORE calling. This is strong, actionable guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.3.0
    • First observedfetch
    • First observedget_context
    • First observedpropose_context_change
    • First observedsearch

TDQS

A3.9/5.0

Scored across 4 tools

Disambiguation3/5

get_context(path) and fetch both read a single context file, so a model could be unsure which to use; get_context's no-argument entry-point behavior and fetch's 'file id from search' purpose do differentiate them somewhat. search and propose_context_change are clearly distinct.

Naming Consistency3/5

get_context and propose_context_change follow a verb_noun pattern, while search and fetch are bare verbs, producing a mixed but readable convention. The names are not chaotic, but they do not form a fully predictable pattern.

Tool Count5/5

Four tools is a well-scoped set for an organizational context repository: an entry point, a search mechanism, an exact file reader, and a change proposal action. None feel gratuitous, and the count is comfortably within the ideal range.

Completeness4/5

The surface covers the core workflow: start from context, search/fetch existing files, and propose coherent changes. There is no direct create/update/delete tool outside propose_context_change, but that appears intentional for a human-reviewed context repo, so the gap is minor.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A Model Context Protocol server that gives AI agents bounded, auditable access to propose changes to an Obsidian vault stored in GitHub, with per-agent expiring tokens, read/write/deny path policies, mutability rules, frontmatter checks, and human-reviewed proposal branches.
    9 npm
    2
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server that helps coding agents research and prepare GitHub contributions by gathering repository guidance, related work, code context, and validation evidence into a local SQLite corpus, without ever writing to GitHub.
    384 npm
    3
    MIT