@markmnl/fmsg-mcp 0.1.0 → 0.1.1
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 +2 -0
- package/dist/config.d.ts +9 -1
- package/dist/config.js +7 -5
- package/dist/context.d.ts +6 -0
- package/dist/context.js +10 -0
- package/dist/index.js +13 -5
- package/dist/public.d.ts +2 -2
- package/dist/public.js +1 -1
- package/package.json +1 -1
- package/server.json +21 -6
package/README.md
CHANGED
|
@@ -120,6 +120,8 @@ attach resources; prompts `chat` and `reply` script the wait → reply loop and
|
|
|
120
120
|
|
|
121
121
|
The API key is exchanged for a short-lived access token that the server renews automatically.
|
|
122
122
|
|
|
123
|
+
Over stdio the server also starts with no credentials at all, so hosts and directories can list its tools; every tool call then returns a message naming the missing variables.
|
|
124
|
+
|
|
123
125
|
## Safety
|
|
124
126
|
|
|
125
127
|
- Sent messages cannot be edited or recalled; send tools say so in their descriptions and are
|
package/dist/config.d.ts
CHANGED
|
@@ -28,4 +28,12 @@ export type ConfigOverrides = {
|
|
|
28
28
|
host?: string;
|
|
29
29
|
port?: number;
|
|
30
30
|
};
|
|
31
|
-
export
|
|
31
|
+
export type LoadConfigOptions = {
|
|
32
|
+
/**
|
|
33
|
+
* stdio only: when false, a missing FMSG_API_URL / FMSG_API_KEY does not throw and
|
|
34
|
+
* `apiUrl` is left empty, so the server can still start and answer introspection
|
|
35
|
+
* (tools/list etc.). Tools then fail with a configuration hint when called.
|
|
36
|
+
*/
|
|
37
|
+
requireCredentials?: boolean;
|
|
38
|
+
};
|
|
39
|
+
export declare function loadConfig(env: NodeJS.ProcessEnv, transport: Transport, overrides?: ConfigOverrides, options?: LoadConfigOptions): Config;
|
package/dist/config.js
CHANGED
|
@@ -37,14 +37,16 @@ function loadDirectory(path) {
|
|
|
37
37
|
}
|
|
38
38
|
return out;
|
|
39
39
|
}
|
|
40
|
-
export function loadConfig(env, transport, overrides = {}) {
|
|
41
|
-
const
|
|
42
|
-
|
|
40
|
+
export function loadConfig(env, transport, overrides = {}, options = {}) {
|
|
41
|
+
const requireCredentials = options.requireCredentials ?? true;
|
|
42
|
+
const apiUrl = env.FMSG_API_URL?.trim() ?? "";
|
|
43
|
+
if (!apiUrl && (transport === "http" || requireCredentials)) {
|
|
43
44
|
throw new Error("FMSG_API_URL is required (base URL of the fmsg Web API, e.g. https://api.example.com)");
|
|
44
|
-
|
|
45
|
+
}
|
|
46
|
+
if (apiUrl && !/^https?:\/\//u.test(apiUrl))
|
|
45
47
|
throw new Error("FMSG_API_URL must start with http:// or https://");
|
|
46
48
|
const apiKey = env.FMSG_API_KEY?.trim();
|
|
47
|
-
if (transport === "stdio" && !apiKey) {
|
|
49
|
+
if (transport === "stdio" && !apiKey && requireCredentials) {
|
|
48
50
|
throw new Error("FMSG_API_KEY is required in stdio mode (an fmsgk_... key for the address this server sends as)");
|
|
49
51
|
}
|
|
50
52
|
if (transport === "http" && apiKey) {
|
package/dist/context.d.ts
CHANGED
|
@@ -17,4 +17,10 @@ export declare class StaticCallerProvider implements CallerProvider {
|
|
|
17
17
|
constructor(client: FmsgClient);
|
|
18
18
|
forRequest(): Promise<Caller>;
|
|
19
19
|
}
|
|
20
|
+
/** stdio without credentials: the server starts (so hosts can list tools) but every tool explains what is missing. */
|
|
21
|
+
export declare class UnconfiguredCallerProvider implements CallerProvider {
|
|
22
|
+
private readonly reason;
|
|
23
|
+
constructor(reason: string);
|
|
24
|
+
forRequest(): Promise<Caller>;
|
|
25
|
+
}
|
|
20
26
|
export declare function callerFor(provider: CallerProvider, ctx: ServerContext): Promise<Caller>;
|
package/dist/context.js
CHANGED
|
@@ -12,6 +12,16 @@ export class StaticCallerProvider {
|
|
|
12
12
|
return this.caller;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
/** stdio without credentials: the server starts (so hosts can list tools) but every tool explains what is missing. */
|
|
16
|
+
export class UnconfiguredCallerProvider {
|
|
17
|
+
reason;
|
|
18
|
+
constructor(reason) {
|
|
19
|
+
this.reason = reason;
|
|
20
|
+
}
|
|
21
|
+
forRequest() {
|
|
22
|
+
return Promise.reject(new Error(this.reason));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
15
25
|
export async function callerFor(provider, ctx) {
|
|
16
26
|
return provider.forRequest(ctx.http?.authInfo);
|
|
17
27
|
}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
5
5
|
import { FmsgClient } from "./client/client.js";
|
|
6
6
|
import { loadConfig, DEFAULT_HTTP_PORT } from "./config.js";
|
|
7
|
-
import { StaticCallerProvider } from "./context.js";
|
|
7
|
+
import { StaticCallerProvider, UnconfiguredCallerProvider } from "./context.js";
|
|
8
8
|
import { createHttpServer, MCP_PATH } from "./http.js";
|
|
9
9
|
import { createFmsgMcpServer } from "./server.js";
|
|
10
10
|
import { PACKAGE_NAME, VERSION } from "./version.js";
|
|
@@ -89,18 +89,26 @@ async function main() {
|
|
|
89
89
|
const transport = args.mode;
|
|
90
90
|
let config;
|
|
91
91
|
try {
|
|
92
|
-
config = loadConfig(process.env, transport, args.overrides);
|
|
92
|
+
config = loadConfig(process.env, transport, args.overrides, { requireCredentials: false });
|
|
93
93
|
}
|
|
94
94
|
catch (error) {
|
|
95
95
|
console.error(`fmsg-mcp: ${error instanceof Error ? error.message : String(error)}`);
|
|
96
96
|
process.exit(2);
|
|
97
97
|
}
|
|
98
98
|
if (transport === "stdio") {
|
|
99
|
-
const client = new FmsgClient(config.apiUrl, config.apiKey);
|
|
100
|
-
const provider = new StaticCallerProvider(client);
|
|
101
99
|
const cfg = config;
|
|
100
|
+
let provider;
|
|
101
|
+
if (cfg.apiUrl && cfg.apiKey) {
|
|
102
|
+
provider = new StaticCallerProvider(new FmsgClient(cfg.apiUrl, cfg.apiKey));
|
|
103
|
+
console.error(`fmsg-mcp ${VERSION} serving stdio for ${cfg.apiUrl}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const missing = [!cfg.apiUrl && "FMSG_API_URL", !cfg.apiKey && "FMSG_API_KEY"].filter(Boolean).join(" and ");
|
|
107
|
+
const reason = `fmsg-mcp is not configured: set ${missing} (the fmsg Web API base URL and an fmsgk_... API key for the address this server sends as)`;
|
|
108
|
+
provider = new UnconfiguredCallerProvider(reason);
|
|
109
|
+
console.error(`fmsg-mcp ${VERSION} serving stdio WITHOUT credentials (${missing} not set): tools are listed but every call will fail until configured`);
|
|
110
|
+
}
|
|
102
111
|
const handle = serveStdio(() => createFmsgMcpServer(provider, cfg));
|
|
103
|
-
console.error(`fmsg-mcp ${VERSION} serving stdio for ${config.apiUrl}`);
|
|
104
112
|
const stop = () => void handle.close().finally(() => process.exit(0));
|
|
105
113
|
process.on("SIGINT", stop);
|
|
106
114
|
process.on("SIGTERM", stop);
|
package/dist/public.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createFmsgMcpServer, SERVER_NAME } from "./server.js";
|
|
2
2
|
export { createHttpServer, type HttpServerHandle } from "./http.js";
|
|
3
|
-
export { loadConfig, type Config, type Transport } from "./config.js";
|
|
4
|
-
export { StaticCallerProvider, type Caller, type CallerProvider } from "./context.js";
|
|
3
|
+
export { loadConfig, type Config, type LoadConfigOptions, type Transport } from "./config.js";
|
|
4
|
+
export { StaticCallerProvider, UnconfiguredCallerProvider, type Caller, type CallerProvider } from "./context.js";
|
|
5
5
|
export { ApiKeyCallerProvider } from "./auth.js";
|
|
6
6
|
export { waitForMessage, type WaitOptions, type WaitResult } from "./wait.js";
|
|
7
7
|
export { assembleThread, renderThread, type AssembledThread } from "./thread.js";
|
package/dist/public.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createFmsgMcpServer, SERVER_NAME } from "./server.js";
|
|
2
2
|
export { createHttpServer } from "./http.js";
|
|
3
3
|
export { loadConfig } from "./config.js";
|
|
4
|
-
export { StaticCallerProvider } from "./context.js";
|
|
4
|
+
export { StaticCallerProvider, UnconfiguredCallerProvider } from "./context.js";
|
|
5
5
|
export { ApiKeyCallerProvider } from "./auth.js";
|
|
6
6
|
export { waitForMessage } from "./wait.js";
|
|
7
7
|
export { assembleThread, renderThread } from "./thread.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markmnl/fmsg-mcp",
|
|
3
3
|
"mcpName": "io.github.markmnl/fmsg-mcp",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"description": "MCP server for fmsg: send and receive federated messages from any AI agent via a deployed fmsg Web API",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
package/server.json
CHANGED
|
@@ -6,18 +6,33 @@
|
|
|
6
6
|
"url": "https://github.com/markmnl/fmsg-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.1",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
14
14
|
"identifier": "@markmnl/fmsg-mcp",
|
|
15
|
-
"version": "0.1.
|
|
16
|
-
"transport": {
|
|
15
|
+
"version": "0.1.1",
|
|
16
|
+
"transport": {
|
|
17
|
+
"type": "stdio"
|
|
18
|
+
},
|
|
17
19
|
"environmentVariables": [
|
|
18
|
-
{
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
{
|
|
21
|
+
"name": "FMSG_API_URL",
|
|
22
|
+
"description": "Base URL of the fmsg Web API",
|
|
23
|
+
"isRequired": true
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "FMSG_API_KEY",
|
|
27
|
+
"description": "fmsg API key (fmsgk_...) for the address to send as",
|
|
28
|
+
"isRequired": true,
|
|
29
|
+
"isSecret": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "FMSG_DEFAULT_DOMAIN",
|
|
33
|
+
"description": "Optional: lets short names resolve to @name@<domain>",
|
|
34
|
+
"isRequired": false
|
|
35
|
+
}
|
|
21
36
|
]
|
|
22
37
|
}
|
|
23
38
|
]
|