@apier-no/mcp 0.1.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/LICENSE +21 -0
- package/README.md +133 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +112 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +122 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PowerLaunch AS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# @apier-no/mcp
|
|
2
|
+
|
|
3
|
+
Thin npm proxy that connects local MCP clients (Claude Desktop, Cursor, Zed, Codex, etc.) to **[Apier](https://www.apier.no)'s hosted Norwegian compliance MCP server** at `https://www.apier.no/api/mcp`.
|
|
4
|
+
|
|
5
|
+
Apier exposes Norwegian government compliance data and actions — Brønnøysund company lookups, Altinn delegations, Skatteetaten obligations, deadline math, regulatory rules — as MCP tools that AI agents can call directly. This package is the local bridge: it runs over stdio in your MCP client and forwards every frame to Apier over Streamable HTTP.
|
|
6
|
+
|
|
7
|
+
## What it is (and what it isn't)
|
|
8
|
+
|
|
9
|
+
**Is:** a ~150-line transport-level passthrough. Your client speaks MCP over stdio; this proxy forwards every frame to `https://www.apier.no/api/mcp` with your `Authorization: Bearer ${APIER_API_KEY}` header attached.
|
|
10
|
+
|
|
11
|
+
**Isn't:** a re-implementation of MCP. All tool / resource / prompt semantics live server-side. When Apier ships a new tool, you don't reinstall this package — the new tool surfaces immediately to your local client.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install -g @apier-no/mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or use `npx` directly in your MCP client config (recommended — no global install needed):
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npx -y @apier-no/mcp
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Get an API key
|
|
26
|
+
|
|
27
|
+
Sign up at [apier.no](https://www.apier.no) and visit your dashboard:
|
|
28
|
+
|
|
29
|
+
→ **<https://www.apier.no/dashboard/keys>**
|
|
30
|
+
|
|
31
|
+
The Free tier ships with one key and enough quota for evaluation. Keys are scoped — Apier rotates them and revokes per-key with no global rollover.
|
|
32
|
+
|
|
33
|
+
## Claude Desktop
|
|
34
|
+
|
|
35
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"apier": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@apier-no/mcp"],
|
|
43
|
+
"env": {
|
|
44
|
+
"APIER_API_KEY": "apier_live_<your_key_here>"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Restart Claude Desktop. The Apier tools (company lookup, obligations, deadlines, etc.) will appear in the tool picker.
|
|
52
|
+
|
|
53
|
+
## Cursor
|
|
54
|
+
|
|
55
|
+
Edit `~/.cursor/mcp.json` (or use Cursor's MCP settings UI):
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"apier": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["-y", "@apier-no/mcp"],
|
|
63
|
+
"env": {
|
|
64
|
+
"APIER_API_KEY": "apier_live_<your_key_here>"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Restart Cursor. Apier tools become available to Cursor's agent.
|
|
72
|
+
|
|
73
|
+
## Other MCP clients
|
|
74
|
+
|
|
75
|
+
Any MCP client that supports the stdio transport works. The pattern is the same: invoke `npx -y @apier-no/mcp` with `APIER_API_KEY` in the environment.
|
|
76
|
+
|
|
77
|
+
## Available tools
|
|
78
|
+
|
|
79
|
+
See **<https://www.apier.no/docs>** for the live tool catalogue and parameter shapes. Tools are versioned server-side; the catalogue is the canonical reference.
|
|
80
|
+
|
|
81
|
+
A non-exhaustive snapshot:
|
|
82
|
+
|
|
83
|
+
- `company.lookup` — Brønnøysund company-registry lookups by org number
|
|
84
|
+
- `company.obligations` — current and upcoming regulatory obligations
|
|
85
|
+
- `company.deadlines` — deadline math (MVA filings, A-melding, årsregnskap, …)
|
|
86
|
+
- `delegations.list` — Altinn delegations for an org number
|
|
87
|
+
- `rules.evaluate` — run an evaluation against the live Apier Rulebook
|
|
88
|
+
|
|
89
|
+
## Configuration
|
|
90
|
+
|
|
91
|
+
| Variable | Default | Description |
|
|
92
|
+
|------------------------|----------------------------------------|----------------------------------------------------------------|
|
|
93
|
+
| `APIER_API_KEY` | **(required, no default)** | Your Apier API key. Get one at the dashboard link above. |
|
|
94
|
+
| `APIER_MCP_ENDPOINT` | `https://www.apier.no/api/mcp` | Override the server URL. **Must be `https://`**; `http://` is rejected. |
|
|
95
|
+
|
|
96
|
+
You can also pass `--endpoint <url>` as a CLI flag (env var has priority for the key — see Security below).
|
|
97
|
+
|
|
98
|
+
## Troubleshooting
|
|
99
|
+
|
|
100
|
+
**1. "APIER_API_KEY environment variable is required."**
|
|
101
|
+
|
|
102
|
+
The proxy could not find an `APIER_API_KEY` in its environment. In MCP-client configs, the env var goes inside the `"env"` object of the server entry — *not* as a CLI argument. Re-read the JSON snippets above; the proxy intentionally refuses CLI-flag keys because `ps aux` and Activity Monitor leak CLI arguments to other local users.
|
|
103
|
+
|
|
104
|
+
**2. "Endpoint must use https://"**
|
|
105
|
+
|
|
106
|
+
You set `APIER_MCP_ENDPOINT` (or `--endpoint`) to an `http://` URL. The proxy refuses plaintext — your API key would be visible to anything on the network path. Apier's production endpoint is `https://www.apier.no/api/mcp`; only override this for local Apier development behind an HTTPS-terminating proxy.
|
|
107
|
+
|
|
108
|
+
**3. Tool calls return "401 Unauthorized" or "403 Forbidden"**
|
|
109
|
+
|
|
110
|
+
Your API key was rejected by Apier. Check at <https://www.apier.no/dashboard/keys> that the key is active and not revoked. If the issue is `403 Forbidden` rather than `401 Unauthorized`, the key is valid but the requested tool requires a higher tier or a scope that the key doesn't carry — the dashboard shows per-key scopes.
|
|
111
|
+
|
|
112
|
+
## Security
|
|
113
|
+
|
|
114
|
+
The proxy is built for the worst case: a malicious or buggy MCP client running on the same machine.
|
|
115
|
+
|
|
116
|
+
- `APIER_API_KEY` is read from the environment **only**. CLI-flag keys are refused — `ps`-listable arguments are a leak channel.
|
|
117
|
+
- `https://` is enforced; `http://` is rejected at startup.
|
|
118
|
+
- The proxy never writes the API key value to stdout, stderr, log files, or error messages. Error formatting uses `err.constructor.name`, never `err.message` (which can carry HTTP header bytes).
|
|
119
|
+
- All diagnostic output goes to stderr; stdout is reserved exclusively for MCP JSON-RPC frames so a stray log line cannot corrupt the protocol stream and crash the client.
|
|
120
|
+
|
|
121
|
+
## Source + issues
|
|
122
|
+
|
|
123
|
+
- Source: <https://github.com/PowerLaunch/apier-mcp>
|
|
124
|
+
- Issues: <https://github.com/PowerLaunch/apier-mcp/issues>
|
|
125
|
+
- Apier docs: <https://www.apier.no/docs>
|
|
126
|
+
|
|
127
|
+
## Versioning
|
|
128
|
+
|
|
129
|
+
Semver. The proxy aims to be stable — most Apier feature additions land server-side and surface to local clients without a republish. Breaking changes to the proxy itself (CLI flags, env vars, supported Node versions) bump minor or major.
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
[MIT](LICENSE) © 2026 PowerLaunch AS
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* apier-mcp CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* Reads APIER_API_KEY from the environment ONLY — never accepts the
|
|
6
|
+
* key as a CLI flag. Process listings (`ps aux`, Activity Monitor)
|
|
7
|
+
* leak CLI arguments to any local user; environment variables are
|
|
8
|
+
* scoped to the process and are the documented MCP-client config
|
|
9
|
+
* pattern (`env: { APIER_API_KEY: "..." }`).
|
|
10
|
+
*
|
|
11
|
+
* Recognised flags:
|
|
12
|
+
* --endpoint <url> Override the default https://www.apier.no/api/mcp
|
|
13
|
+
* (or set APIER_MCP_ENDPOINT env var)
|
|
14
|
+
* --version, -v Print version and exit
|
|
15
|
+
* --help, -h Print usage and exit
|
|
16
|
+
*/
|
|
17
|
+
import { startProxy } from "./index.js";
|
|
18
|
+
// Keep in sync with package.json#version. Hardcoded rather than read at
|
|
19
|
+
// runtime so a bundled binary doesn't need fs access. The build script
|
|
20
|
+
// (and prepublishOnly hook) is the discipline that keeps this honest.
|
|
21
|
+
const VERSION = "0.1.0";
|
|
22
|
+
const HELP = `apier-mcp ${VERSION} — Thin proxy to Apier's hosted MCP server.
|
|
23
|
+
|
|
24
|
+
Usage: apier-mcp [options]
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--endpoint <url> Override default https://www.apier.no/api/mcp
|
|
28
|
+
(or set APIER_MCP_ENDPOINT)
|
|
29
|
+
--version, -v Print version and exit
|
|
30
|
+
--help, -h Print this help and exit
|
|
31
|
+
|
|
32
|
+
Required environment variable:
|
|
33
|
+
APIER_API_KEY Get a key at https://www.apier.no/dashboard/keys
|
|
34
|
+
|
|
35
|
+
Example MCP client config (Claude Desktop / Cursor):
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"apier": {
|
|
39
|
+
"command": "npx",
|
|
40
|
+
"args": ["-y", "@apier-no/mcp"],
|
|
41
|
+
"env": { "APIER_API_KEY": "apier_live_<your_key>" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Docs: https://www.apier.no/docs
|
|
47
|
+
Issues: https://github.com/PowerLaunch/apier-mcp/issues
|
|
48
|
+
`;
|
|
49
|
+
function parseArgs(argv) {
|
|
50
|
+
let endpoint;
|
|
51
|
+
let showHelp = false;
|
|
52
|
+
let showVersion = false;
|
|
53
|
+
for (let i = 0; i < argv.length; i++) {
|
|
54
|
+
const arg = argv[i];
|
|
55
|
+
if (arg === "--help" || arg === "-h") {
|
|
56
|
+
showHelp = true;
|
|
57
|
+
}
|
|
58
|
+
else if (arg === "--version" || arg === "-v") {
|
|
59
|
+
showVersion = true;
|
|
60
|
+
}
|
|
61
|
+
else if (arg === "--endpoint") {
|
|
62
|
+
const next = argv[i + 1];
|
|
63
|
+
if (typeof next !== "string" || next.length === 0) {
|
|
64
|
+
return {
|
|
65
|
+
showHelp: false,
|
|
66
|
+
showVersion: false,
|
|
67
|
+
error: "--endpoint requires a URL argument.",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
endpoint = next;
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
return {
|
|
75
|
+
showHelp: false,
|
|
76
|
+
showVersion: false,
|
|
77
|
+
error: `Unknown argument: ${arg}`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { endpoint, showHelp, showVersion };
|
|
82
|
+
}
|
|
83
|
+
async function main() {
|
|
84
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
85
|
+
if (parsed.error !== undefined) {
|
|
86
|
+
process.stderr.write(`apier-mcp: ${parsed.error}\n\n${HELP}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
if (parsed.showHelp) {
|
|
90
|
+
// Help goes to stderr (NOT stdout) — stdout is reserved for MCP
|
|
91
|
+
// JSON-RPC frames. A user running `apier-mcp --help` sees the
|
|
92
|
+
// text the same way regardless of stream.
|
|
93
|
+
process.stderr.write(HELP);
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
if (parsed.showVersion) {
|
|
97
|
+
process.stderr.write(`apier-mcp ${VERSION}\n`);
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await startProxy({ endpoint: parsed.endpoint });
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
// Last-resort error handler. Never echo err.message — Supabase /
|
|
105
|
+
// network error strings can carry token fragments or header
|
|
106
|
+
// bytes. Only the constructor name is safe.
|
|
107
|
+
const name = err instanceof Error ? err.constructor.name : typeof err;
|
|
108
|
+
process.stderr.write(`apier-mcp: fatal error (${name})\n`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
void main();
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @apier-no/mcp — Thin transport-level proxy that bridges a local stdio
|
|
3
|
+
* MCP client (Claude Desktop, Cursor, etc.) to Apier's hosted MCP
|
|
4
|
+
* server over Streamable HTTP.
|
|
5
|
+
*
|
|
6
|
+
* The proxy is intentionally a pure-passthrough pipe at the transport
|
|
7
|
+
* level — it never inspects, decodes, or rewrites MCP protocol frames.
|
|
8
|
+
* All tool / resource / prompt semantics live server-side at
|
|
9
|
+
* https://www.apier.no/api/mcp; a thin proxy makes the local client
|
|
10
|
+
* transparent to MCP-protocol additions without requiring an npm
|
|
11
|
+
* republish.
|
|
12
|
+
*
|
|
13
|
+
* SECURITY:
|
|
14
|
+
* - APIER_API_KEY is read from the environment ONLY (never CLI
|
|
15
|
+
* flag — `ps aux` would leak it). Missing or empty key exits 1
|
|
16
|
+
* with a helpful stderr message.
|
|
17
|
+
* - HTTP endpoint is rejected if not https:// — Apier is HTTPS-only.
|
|
18
|
+
* - ALL diagnostic output goes to stderr; stdout is reserved for
|
|
19
|
+
* MCP JSON-RPC frames (corrupting stdout with a stray log line
|
|
20
|
+
* breaks the MCP client).
|
|
21
|
+
* - APIER_API_KEY value is NEVER written to stderr (or anywhere).
|
|
22
|
+
* Error messages format only `err.name` / `err.constructor.name`,
|
|
23
|
+
* never the message which could carry header / auth bytes.
|
|
24
|
+
*/
|
|
25
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
26
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
27
|
+
const DEFAULT_ENDPOINT = "https://www.apier.no/api/mcp";
|
|
28
|
+
export async function startProxy(options = {}) {
|
|
29
|
+
// ── API key ─────────────────────────────────────────────────
|
|
30
|
+
const apiKey = process.env.APIER_API_KEY;
|
|
31
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
32
|
+
process.stderr.write("apier-mcp: APIER_API_KEY environment variable is required.\n" +
|
|
33
|
+
" Get a key at https://www.apier.no/dashboard/keys\n" +
|
|
34
|
+
" Then add it to your MCP client config (example for Claude Desktop):\n" +
|
|
35
|
+
' "env": { "APIER_API_KEY": "apier_live_<your_key>" }\n');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
// ── Endpoint resolution + HTTPS-only enforcement ────────────
|
|
39
|
+
const rawEndpoint = options.endpoint ?? process.env.APIER_MCP_ENDPOINT ?? DEFAULT_ENDPOINT;
|
|
40
|
+
let endpointUrl;
|
|
41
|
+
try {
|
|
42
|
+
endpointUrl = new URL(rawEndpoint);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
process.stderr.write(`apier-mcp: invalid endpoint URL "${rawEndpoint}". Expected an https:// URL.\n`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
if (endpointUrl.protocol !== "https:") {
|
|
49
|
+
process.stderr.write(`apier-mcp: endpoint must use https:// (got "${endpointUrl.protocol}//"). Apier's MCP server is HTTPS-only — http:// would expose API keys in transit.\n`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
process.stderr.write(`apier-mcp: connecting to ${endpointUrl.href}\n`);
|
|
53
|
+
// ── Transports ─────────────────────────────────────────────
|
|
54
|
+
// StreamableHTTPClientTransport: outbound link to Apier.
|
|
55
|
+
// The Authorization header is set via requestInit so it threads
|
|
56
|
+
// through every HTTP request the transport makes.
|
|
57
|
+
const httpTransport = new StreamableHTTPClientTransport(endpointUrl, {
|
|
58
|
+
requestInit: {
|
|
59
|
+
headers: {
|
|
60
|
+
Authorization: `Bearer ${apiKey}`,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
// StdioServerTransport: local link to Claude Desktop / Cursor /
|
|
65
|
+
// any stdio-MCP client. Reads framed messages from stdin, writes
|
|
66
|
+
// to stdout.
|
|
67
|
+
const stdioTransport = new StdioServerTransport();
|
|
68
|
+
// ── Bridge ─────────────────────────────────────────────────
|
|
69
|
+
// Pure transport-level passthrough. We never decode MCP frames,
|
|
70
|
+
// so a future protocol version with new methods works without a
|
|
71
|
+
// republish. The MCP session state lives end-to-end between the
|
|
72
|
+
// local client and the Apier server — we're just plumbing.
|
|
73
|
+
stdioTransport.onmessage = (message) => {
|
|
74
|
+
void httpTransport.send(message).catch((err) => {
|
|
75
|
+
// Log only the error constructor name — error.message can
|
|
76
|
+
// carry header bytes or fragments of the request body.
|
|
77
|
+
const name = err instanceof Error ? err.constructor.name : typeof err;
|
|
78
|
+
process.stderr.write(`apier-mcp: client→server forward failed (${name})\n`);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
httpTransport.onmessage = (message) => {
|
|
82
|
+
void stdioTransport.send(message).catch((err) => {
|
|
83
|
+
const name = err instanceof Error ? err.constructor.name : typeof err;
|
|
84
|
+
process.stderr.write(`apier-mcp: server→client forward failed (${name})\n`);
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
// ── Graceful shutdown ──────────────────────────────────────
|
|
88
|
+
let shuttingDown = false;
|
|
89
|
+
const handleShutdown = async (signal) => {
|
|
90
|
+
if (shuttingDown)
|
|
91
|
+
return;
|
|
92
|
+
shuttingDown = true;
|
|
93
|
+
process.stderr.write(`apier-mcp: ${signal} received, closing transports.\n`);
|
|
94
|
+
try {
|
|
95
|
+
await stdioTransport.close();
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
const name = err instanceof Error ? err.constructor.name : typeof err;
|
|
99
|
+
process.stderr.write(`apier-mcp: stdio close error (${name})\n`);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
await httpTransport.close();
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const name = err instanceof Error ? err.constructor.name : typeof err;
|
|
106
|
+
process.stderr.write(`apier-mcp: http close error (${name})\n`);
|
|
107
|
+
}
|
|
108
|
+
process.exit(0);
|
|
109
|
+
};
|
|
110
|
+
process.on("SIGINT", () => {
|
|
111
|
+
void handleShutdown("SIGINT");
|
|
112
|
+
});
|
|
113
|
+
process.on("SIGTERM", () => {
|
|
114
|
+
void handleShutdown("SIGTERM");
|
|
115
|
+
});
|
|
116
|
+
// ── Start ──────────────────────────────────────────────────
|
|
117
|
+
// Start HTTP first so the local client sees a ready proxy by
|
|
118
|
+
// the time stdin starts emitting frames.
|
|
119
|
+
await httpTransport.start();
|
|
120
|
+
await stdioTransport.start();
|
|
121
|
+
process.stderr.write("apier-mcp: ready, bridging messages.\n");
|
|
122
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apier-no/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Thin npm proxy: connect local MCP clients (Claude Desktop, Cursor) to Apier's hosted Norwegian compliance MCP server.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"apier-mcp": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"lint": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build && npm test"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/PowerLaunch/apier-mcp.git"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://www.apier.no",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/PowerLaunch/apier-mcp/issues"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"mcp",
|
|
38
|
+
"model-context-protocol",
|
|
39
|
+
"apier",
|
|
40
|
+
"norway",
|
|
41
|
+
"norwegian-compliance",
|
|
42
|
+
"altinn",
|
|
43
|
+
"skatteetaten",
|
|
44
|
+
"claude",
|
|
45
|
+
"cursor"
|
|
46
|
+
],
|
|
47
|
+
"author": "PowerLaunch AS",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
51
|
+
"zod": "^4.4.3"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.7.0",
|
|
55
|
+
"tsx": "^4.21.0",
|
|
56
|
+
"typescript": "^6.0.3",
|
|
57
|
+
"vitest": "^4.1.6"
|
|
58
|
+
}
|
|
59
|
+
}
|