@oriva/mcp-server 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -5
- package/dist/client.js +56 -48
- package/dist/index.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -2,7 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Model Context Protocol server for the [Oriva](https://api.oriva.io) public API.
|
|
4
4
|
|
|
5
|
-
Exposes
|
|
5
|
+
Exposes 46 public Oriva API endpoints as MCP tools so AI agents (Claude Code, Cursor, Continue, Claude Desktop) can read and write Oriva data on behalf of a user with an `oriva_pk_live_*` Personal Access Token.
|
|
6
|
+
|
|
7
|
+
## Get a Personal Access Token
|
|
8
|
+
|
|
9
|
+
1. Sign in to [oriva.io](https://oriva.io)
|
|
10
|
+
2. Go to [Settings → Personal Access Tokens](https://oriva.io/settings/personal-access-tokens)
|
|
11
|
+
3. Click **Create Token**, name it (e.g. `claude-code`), and optionally set an expiry
|
|
12
|
+
4. **Copy the token now** — the full value is shown only once
|
|
13
|
+
5. Treat it like a password — never commit it to git, never paste it into chat
|
|
14
|
+
|
|
15
|
+
Token format: `oriva_pk_live_<48 hex chars>`. The token grants read+write on your account; revoke any time from the same settings page.
|
|
6
16
|
|
|
7
17
|
## Install + connect (Claude Code)
|
|
8
18
|
|
|
@@ -16,12 +26,53 @@ Then in any Claude Code session, `/mcp` lists `oriva` and you can ask things lik
|
|
|
16
26
|
- "list my marketplace apps with oriva"
|
|
17
27
|
- "create an Oriva event titled 'Demo Day' on 2026-06-01"
|
|
18
28
|
|
|
29
|
+
## Install + connect (other MCP clients)
|
|
30
|
+
|
|
31
|
+
For clients that read a JSON config file (Claude Desktop, Cursor, Continue, etc.), add this entry to your MCP config — the exact filename and location differs per client, see your client's docs.
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"oriva": {
|
|
37
|
+
"command": "npx",
|
|
38
|
+
"args": ["-y", "@oriva/mcp-server"],
|
|
39
|
+
"env": {
|
|
40
|
+
"ORIVA_API_KEY": "oriva_pk_live_xxx"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Common config locations:
|
|
48
|
+
|
|
49
|
+
| Client | Config file |
|
|
50
|
+
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) / `%APPDATA%\Claude\claude_desktop_config.json` (Windows) |
|
|
52
|
+
| Cursor | `~/.cursor/mcp.json` (user-level) or `<project>/.cursor/mcp.json` (project-level) |
|
|
53
|
+
| Continue | `~/.continue/config.json` under the `experimental.modelContextProtocolServers` key |
|
|
54
|
+
| Project-level (any client supporting `.mcp.json`) | `<project-root>/.mcp.json` |
|
|
55
|
+
|
|
56
|
+
Restart the client after editing the config. The Oriva tools appear in the client's tool picker once the connection succeeds.
|
|
57
|
+
|
|
58
|
+
## Troubleshooting
|
|
59
|
+
|
|
60
|
+
| Symptom | Likely cause | Fix |
|
|
61
|
+
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
62
|
+
| Tool call returns `isError: true` with `HTTP 401 / INVALID_API_KEY` | `ORIVA_API_KEY` is missing, has whitespace, or is wrong | Re-export the env var, verify with `echo "$ORIVA_API_KEY" \| head -c 14` (should print `oriva_pk_live_`) |
|
|
63
|
+
| Tool call returns `HTTP 401 / API_KEY_EXPIRED` | The token's `expires_at` is in the past | Mint a fresh token at [Settings → Personal Access Tokens](https://oriva.io/settings/personal-access-tokens) and update the env var |
|
|
64
|
+
| Tool call returns `HTTP 401 / API_KEY_INACTIVE` | Token was revoked | Mint a new one |
|
|
65
|
+
| Tool call returns `HTTP 401 / Invalid API key format` | Token doesn't start with `oriva_pk_live_` (e.g. you pasted a JWT or a developer-app key) | Generate a PAT — see "Get a Personal Access Token" above |
|
|
66
|
+
| Server fails at boot: `ORIVA_API_KEY environment variable is required` | Env var not reaching the spawned process | Most MCP clients require env vars under an `env` key in the JSON config, not inherited from the shell |
|
|
67
|
+
| `/mcp` in Claude Code shows oriva but tool count is 0 | The bundled spec failed to parse, or `npx` couldn't download the package | Run `npx @oriva/mcp-server` manually with `ORIVA_API_KEY` set — the stderr line `[oriva-mcp] Loaded N tools from spec` tells you the actual count, plus any parse errors |
|
|
68
|
+
| Old version of the package keeps running after upgrade | `npx` caches packages by name+version | Force-refresh: `npx -y @oriva/mcp-server@latest` |
|
|
69
|
+
|
|
19
70
|
## Environment variables
|
|
20
71
|
|
|
21
|
-
| Variable | Required | Purpose
|
|
22
|
-
| -------------------- | -------- |
|
|
23
|
-
| `ORIVA_API_KEY` | yes |
|
|
24
|
-
| `ORIVA_API_BASE_URL` | no | Override the API base URL (default `https://api.oriva.io`). Useful for local development against a tunnel.
|
|
72
|
+
| Variable | Required | Purpose |
|
|
73
|
+
| -------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
74
|
+
| `ORIVA_API_KEY` | yes | `oriva_pk_live_*` Personal Access Token used as the `Authorization: Bearer …` header. Generate at https://oriva.io/settings/personal-access-tokens (see "Get a Personal Access Token" above). |
|
|
75
|
+
| `ORIVA_API_BASE_URL` | no | Override the API base URL (default `https://api.oriva.io`). Useful for local development against a tunnel. |
|
|
25
76
|
|
|
26
77
|
## What's exposed
|
|
27
78
|
|
|
@@ -38,6 +89,7 @@ Every public Oriva API endpoint that the OpenAPI spec marks with an `operationId
|
|
|
38
89
|
- First-party tenant routes (`/api/v1/tenant/*`) — never part of the public contract
|
|
39
90
|
- Internal debug / dev routes (`/dev-profiles`, `/api/v1/debug/cors`)
|
|
40
91
|
- Admin routes that require a separate `requireAdminToken`
|
|
92
|
+
- Personal Access Token management routes (`POST/GET/DELETE /api/v1/me/tokens`) — these require a Supabase session JWT, not a PAT, because of a chain-of-trust constraint: a PAT cannot mint or revoke another PAT. Manage tokens from the web at [oriva.io/settings/personal-access-tokens](https://oriva.io/settings/personal-access-tokens) instead. The routes still exist on the live API for browser clients; only the MCP tool projection is filtered.
|
|
41
93
|
|
|
42
94
|
The complete list lives in `claudedocs/public-api-contract.md` in the o-platform repo.
|
|
43
95
|
|
|
@@ -77,6 +129,21 @@ To add the locally-built server to Claude Code:
|
|
|
77
129
|
claude mcp add oriva-dev -e ORIVA_API_KEY=oriva_pk_live_xxx -- node $PWD/dist/index.js
|
|
78
130
|
```
|
|
79
131
|
|
|
132
|
+
## Changelog
|
|
133
|
+
|
|
134
|
+
See [CHANGELOG.md](./CHANGELOG.md) for what changed in each release.
|
|
135
|
+
|
|
136
|
+
## Reporting issues
|
|
137
|
+
|
|
138
|
+
Open an issue at https://github.com/0riva/o-platform/issues with the `mcp-server` label. Include:
|
|
139
|
+
|
|
140
|
+
- The MCP client you're using (Claude Code, Claude Desktop, Cursor, etc.) and its version
|
|
141
|
+
- The output of `npx @oriva/mcp-server@latest --help` if it errors at boot, OR the `[oriva-mcp] Loaded N tools` line if it boots cleanly
|
|
142
|
+
- The tool call that misbehaved (tool name + the arguments you passed, redacting any PII)
|
|
143
|
+
- The actual response (`HTTP <status>` + body), redacting `Authorization` headers and PAT values
|
|
144
|
+
|
|
145
|
+
Never paste your `ORIVA_API_KEY` value into an issue — only the `oriva_pk_live_` prefix is safe to share for diagnostics.
|
|
146
|
+
|
|
80
147
|
## License
|
|
81
148
|
|
|
82
149
|
MIT — see [LICENSE](../../LICENSE) in the o-platform repo root.
|
package/dist/client.js
CHANGED
|
@@ -1,55 +1,63 @@
|
|
|
1
|
+
import { rawClient, rawSdk } from '@oriva/sdk';
|
|
1
2
|
const DEFAULT_BASE_URL = 'https://api.oriva.io';
|
|
2
|
-
|
|
3
|
+
let configuredKey;
|
|
4
|
+
let configuredBaseUrl;
|
|
5
|
+
function ensureClientConfigured(options) {
|
|
3
6
|
const baseUrl = options.baseUrl ?? process.env.ORIVA_API_BASE_URL ?? DEFAULT_BASE_URL;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
if (configuredKey === options.apiKey && configuredBaseUrl === baseUrl)
|
|
8
|
+
return;
|
|
9
|
+
rawClient.setConfig({
|
|
10
|
+
baseUrl,
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
13
|
+
'User-Agent': '@oriva/mcp-server/0.2.0',
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
configuredKey = options.apiKey;
|
|
17
|
+
configuredBaseUrl = baseUrl;
|
|
18
|
+
}
|
|
19
|
+
function pickByKeys(args, keys) {
|
|
20
|
+
if (keys.length === 0)
|
|
21
|
+
return undefined;
|
|
22
|
+
const out = {};
|
|
23
|
+
for (const k of keys) {
|
|
24
|
+
if (args[k] !== undefined)
|
|
25
|
+
out[k] = args[k];
|
|
11
26
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
else {
|
|
22
|
-
qs.set(name, String(value));
|
|
23
|
-
}
|
|
27
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
28
|
+
}
|
|
29
|
+
function buildBody(args, bodyFields) {
|
|
30
|
+
if (bodyFields.length === 0)
|
|
31
|
+
return undefined;
|
|
32
|
+
const out = {};
|
|
33
|
+
for (const { alias, original } of bodyFields) {
|
|
34
|
+
if (args[alias] !== undefined)
|
|
35
|
+
out[original] = args[alias];
|
|
24
36
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (args[alias] !== undefined)
|
|
33
|
-
bodyObj[original] = args[alias];
|
|
34
|
-
}
|
|
35
|
-
if (Object.keys(bodyObj).length > 0) {
|
|
36
|
-
body = JSON.stringify(bodyObj);
|
|
37
|
-
contentType = 'application/json';
|
|
38
|
-
}
|
|
37
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
38
|
+
}
|
|
39
|
+
export async function callOperation(op, args, options) {
|
|
40
|
+
ensureClientConfigured(options);
|
|
41
|
+
const fn = rawSdk[op.toolName];
|
|
42
|
+
if (typeof fn !== 'function') {
|
|
43
|
+
throw new Error(`No SDK method for operationId: ${op.toolName}`);
|
|
39
44
|
}
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
const sdkOptions = {};
|
|
46
|
+
const path = pickByKeys(args, op.pathParams);
|
|
47
|
+
const query = pickByKeys(args, op.queryParams);
|
|
48
|
+
const body = buildBody(args, op.bodyFields);
|
|
49
|
+
if (path)
|
|
50
|
+
sdkOptions.path = path;
|
|
51
|
+
if (query)
|
|
52
|
+
sdkOptions.query = query;
|
|
53
|
+
if (body)
|
|
54
|
+
sdkOptions.body = body;
|
|
55
|
+
const result = await fn(sdkOptions);
|
|
56
|
+
const payload = result.data ?? result.error ?? null;
|
|
57
|
+
const text = payload === null ? '' : typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
58
|
+
return {
|
|
59
|
+
status: result.response.status,
|
|
60
|
+
text,
|
|
61
|
+
ok: result.response.ok,
|
|
45
62
|
};
|
|
46
|
-
if (contentType)
|
|
47
|
-
headers['Content-Type'] = contentType;
|
|
48
|
-
const res = await fetch(url, {
|
|
49
|
-
method: op.method.toUpperCase(),
|
|
50
|
-
headers,
|
|
51
|
-
body,
|
|
52
|
-
});
|
|
53
|
-
const text = await res.text();
|
|
54
|
-
return { status: res.status, text, ok: res.ok };
|
|
55
63
|
}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { dirname, join } from 'node:path';
|
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
6
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
|
-
import { CallToolRequestSchema, ListToolsRequestSchema
|
|
7
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { callOperation } from './client.js';
|
|
9
9
|
import { getSpecInfo, projectTools } from './openapi.js';
|
|
10
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oriva/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Model Context Protocol server for the Oriva public API. Exposes all 46 public endpoints as MCP tools for use in Claude Code, Cursor, Continue, and Claude Desktop.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"start": "node dist/index.js"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@modelcontextprotocol/sdk": "^1.6.0"
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.6.0",
|
|
25
|
+
"@oriva/sdk": "^0.1.0"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@types/node": "^20.0.0",
|