advocatehub-mcp
# advocatehub-mcp
A [Model Context Protocol](https://modelcontextprotocol.io) server for
[Influitive AdvocateHub](https://www.influitive.com/), built entirely on the
public Influitive REST API (`api.influitive.com` / `api.influitives.com` in
staging). This is **Phase 1**: no hub source changes, no internal endpoints —
everything here is something any AdvocateHub customer could build against
their own API token.
## What it does
**55 org-token tools** (members, groups, challenges, events, rewards, approvals,
referrals, references, webhooks, messages, integrations, and more) plus
**25 individual-user SSO / JWT self-service tools** (`sso_login`, `whoami`,
`sso_logout`, and 22 `my_*` tools covering profile, groups, challenges, rewards,
activity, notifications, badges/achievements, and social auth). Org-token writes
are confirm-gated and audit-logged; SSO tools sign a human into their own hub
account via a real browser and call the hub as *them*, separate from the org-wide
API token.
**Tool surface (HTTP-first):** streamable HTTP defaults to the **gateway** surface
(~20 category tools). Set header `X-Advocatehub-Tool-Surface: granular` for the full
**~83** granular catalog (e.g. Cursor). Claude Desktop is auto-detected from MCP
`initialize` clientInfo. Stdio defaults to **granular** unless
`ADVOCATEHUB_TOOL_SURFACE=gateway`. See [docs/tool-reference.md](docs/tool-reference.md)
for gateway actions and [docs/setup-claude.md](docs/setup-claude.md) for setup.
## Status
- **P1a (stdio, for Claude Desktop/Code): done.** See
[docs/setup-claude.md](docs/setup-claude.md).
- **P1b (streamable HTTP, for ChatGPT / remote clients): done, needs a staging
smoke pass.** See [docs/setup-chatgpt.md](docs/setup-chatgpt.md).
- **Individual-user SSO/JWT self-service (`sso_login`/`whoami`/`sso_logout` + 22 `my_*` tools,
see `src/tools/myAccount.ts` and `src/tools/sso.ts`): done for stdio only.** See
[docs/setup-sso.md](docs/setup-sso.md). Not yet available on the streamable
HTTP transport.
- Target environment so far: **staging** (`https://api.influitives.com`).
Production support is a config change (`X-Influitive-Base-Url` header or
`INFLUITIVE_BASE_URL` env var to `https://api.influitive.com`) — re-run the
staging smoke checklist against production before trusting it there.
## Optimization roadmap
File-grounded improvement plans by credential model:
- **Org token + org id** (integration / admin bot): [docs/optimization-plan-org-token.md](docs/optimization-plan-org-token.md)
- **Individual JWT / SSO** (self-service, signed-in human): [docs/optimization-plan-jwt-sso.md](docs/optimization-plan-jwt-sso.md)
- **Both credentials** (hybrid stdio deployments): [docs/optimization-plan-hybrid.md](docs/optimization-plan-hybrid.md)
See also [JWT_INDIVIDUAL_USER_AUTH_CAPABILITY_MATRIX.md](JWT_INDIVIDUAL_USER_AUTH_CAPABILITY_MATRIX.md) for what each credential can and cannot do today.
## Quick start (HTTP — recommended)
```bash
npm install
npm run build
npm run start:http # listens on PORT (default 8787), no credentials needed
```
Point your MCP client at `http://localhost:8787/mcp` with per-connection headers:
```json
{
"mcpServers": {
"advocatehub": {
"type": "http",
"url": "http://localhost:8787/mcp",
"headers": {
"Authorization": "Bearer <INFLUITIVE_API_TOKEN>",
"X-Influitive-Org-Id": "<ORG_ID>",
"X-Influitive-Base-Url": "https://api.influitives.com"
}
}
}
}
```
See [docs/setup-claude.md](docs/setup-claude.md) and [docs/setup-chatgpt.md](docs/setup-chatgpt.md)
for Claude Desktop, Claude Code (`claude mcp add --transport http`), and ChatGPT setup.
See [docs/usage-guide.md](docs/usage-guide.md) for credential modes and which tools each auth type exposes.
## Quick start (stdio)
```bash
npm install
npm run build
npm run start # or point your client's config at dist/src/index.js
```
Supply credentials via client `env` vars (`INFLUITIVE_API_TOKEN`, `INFLUITIVE_ORG_ID`)
or call the `configure_tenant` tool at session start. No `.env` file or setup
wizard required.
### Hybrid mode (org token + SSO on one machine)
Use stdio transport and configure **both** credentials:
```bash
# Org-wide integration bot (required for admin tools)
INFLUITIVE_BASE_URL=https://api.influitives.com
INFLUITIVE_API_TOKEN=<from hub Admin -> Integrations -> Influitive API>
INFLUITIVE_ORG_ID=<numeric org id>
# Individual-user SSO (required for sso_login / whoami / my_* tools)
INFLUITIVE_HUB_URL=https://yourhub.influitives.com
```
Or pass `hub_url` to `configure_tenant` alongside `api_token` and `org_id`.
After configuration, run `sso_login` once interactively to seed the browser profile. SSO tools do not work on streamable HTTP — see [docs/setup-sso.md](docs/setup-sso.md) and [docs/optimization-plan-hybrid.md](docs/optimization-plan-hybrid.md).
## Development
```bash
npm run dev # tsx watch, stdio
npm run dev:http # tsx watch, streamable HTTP
npm test # unit tests (mocked fetch, no network)
npm run test:integration # opt-in, hits real staging — see .env.example
npm run lint
npm run typecheck
```
## Repo layout
```
src/
index.ts stdio entrypoint (P1a)
http.ts streamable HTTP entrypoint (P1b)
server.ts builds the McpServer and registers all tools
config/ tenant session, HTTP header resolution, env bootstrap, SSO session cache
client/ InfluitiveClient: auth headers, retries, cursor pagination, rate limiting
auth/ HubSsoClient: Playwright-driven individual-user SSO login (see docs/setup-sso.md)
errors/ typed error classes + HTTP status -> error mapping
registry/ local per-tenant index of challenges this server has created
audit/ append-only JSONL write audit log (monthly rotation)
tools/ ~55 org-token tools + configure_tenant + 25 SSO/JWT self-service tools
test/
unit/ fast tests, fetch mocked, no network
integration/ opt-in, mutates a real (disposable) staging tenant
docs/ setup guides, usage guide, tool reference
```
## Design notes worth knowing before you touch this
- **Plug-and-play credentials:** the server starts unconfigured. HTTP clients
pass `Authorization`, `X-Influitive-Org-Id`, and optionally
`X-Influitive-Base-Url` per connection. Stdio clients use env vars or
`configure_tenant` at runtime.
- **Write safety:** every write tool takes a `confirm` flag. `confirm:false`
(or omitted) only previews — it never calls the API. `confirm:true` executes
and always appends exactly one entry to the per-tenant audit log
(`~/.advocatehub-mcp/audit/<orgId>-YYYY-MM.jsonl`, with legacy
`<orgId>.jsonl` still read), whether it succeeded or failed.
See `src/tools/shared/confirmGate.ts`.
- **No raw exceptions cross the MCP boundary.** Every tool handler is wrapped
so typed errors (`AuthError`, `NotFoundError`, ...) come back as
`{ isError: true }` text, never an unhandled throw. See
`src/tools/shared/formatters.ts`.
- **The public API has no "list challenges" endpoint.** `ChallengeRegistry`
(`src/registry/challengeRegistry.ts`) is a local, best-effort index of
challenges *this server* created — it does not know about challenges
created any other way, and is lost if `~/.advocatehub-mcp` is wiped.
- **`contacts_api_search` is a per-tenant Labs flag.** If it's off, `/contacts`
silently ignores filters instead of erroring. `search_members` refuses
filtered queries once it knows the flag is off (`config.contactsSearchEnabled
=== false`), and self-heals that cache the first time it sees evidence
either way. See `src/tools/members.ts`.
- **Locking a member is seat reclaim**, per current product policy: it blocks
login and excludes the member from advocate counts, targeting, and the
billable seat count. `deactivate_member`/`reactivate_member` describe this
explicitly in their tool descriptions so an LLM doesn't undersell what the
action does.
TDQS
Scored across 5 tools
The tools are mostly distinct: list_advocatehub_tools for discovery, configure_tenant for setup, get_active_identity_context for session context. The only potential confusion is between audit_tail and audit_search, but they are differentiated by recency vs. filtered search, and the descriptions clarify the distinction.
All tool names use snake_case and are readable. Most follow a verb_first pattern (list_, configure_, get_), but audit_tail and audit_search place the resource (audit) before the verb, a minor deviation from the otherwise consistent convention.
With five tools, the count falls within the typical 3-15 range and feels reasonable for a utility/admin-focused server. It is slightly on the smaller side given the apparent domain, but not inappropriately sparse.
The server name and list_advocatehub_tools description reference domain objects like members, rewards, and challenges, yet none of the actual tools perform any domain operations. The set is limited to configuration, identity, and audit utilities, leaving the core AdvocateHub functionality completely absent. Even within the meta-purpose, there is no way to modify configuration or manage audit logs beyond reading them.