@ionhour/mcp-server 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/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # @ionhour/mcp-server
2
+
3
+ Connect AI assistants to your [IonHour](https://ionhour.com) uptime monitoring workspace using the [Model Context Protocol](https://modelcontextprotocol.io).
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Set your API key
9
+ export IONHOUR_API_KEY=ionh_your_key_here
10
+
11
+ # Run with npx (no install needed)
12
+ npx @ionhour/mcp-server
13
+ ```
14
+
15
+ ## Setup with AI Assistants
16
+
17
+ ### Claude Code
18
+
19
+ ```bash
20
+ claude mcp add ionhour -- npx @ionhour/mcp-server
21
+ ```
22
+
23
+ ### Claude Desktop
24
+
25
+ Add to your `claude_desktop_config.json`:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "ionhour": {
31
+ "command": "npx",
32
+ "args": ["@ionhour/mcp-server"],
33
+ "env": {
34
+ "IONHOUR_API_KEY": "ionh_your_key_here"
35
+ }
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### Cursor
42
+
43
+ Add to your `.cursor/mcp.json`:
44
+
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "ionhour": {
49
+ "command": "npx",
50
+ "args": ["@ionhour/mcp-server"],
51
+ "env": {
52
+ "IONHOUR_API_KEY": "ionh_your_key_here"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### VS Code (Copilot)
60
+
61
+ Add to your `.vscode/mcp.json`:
62
+
63
+ ```json
64
+ {
65
+ "servers": {
66
+ "ionhour": {
67
+ "command": "npx",
68
+ "args": ["@ionhour/mcp-server"],
69
+ "env": {
70
+ "IONHOUR_API_KEY": "ionh_your_key_here"
71
+ }
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## Getting an API Key
78
+
79
+ 1. Go to your IonHour workspace **Settings > API Keys**
80
+ 2. Create a new key with **Read & Write** or **Read Only** permission
81
+ 3. Copy the key (starts with `ionh_`)
82
+
83
+ ## Available Tools
84
+
85
+ ### Workspace
86
+ - `get_workspace` - Get workspace details
87
+ - `get_workspace_summary` - Overview of projects, checks, and incidents
88
+ - `get_workspace_reliability` - Uptime, incident count, and MTTR metrics
89
+ - `list_team_members` - List workspace members and roles
90
+ - `send_invitation` - Invite users to the workspace
91
+
92
+ ### Projects
93
+ - `list_projects` / `create_project` / `update_project`
94
+
95
+ ### Checks (Monitors)
96
+ - `register_check` - Create a new monitoring check
97
+ - `list_checks` / `list_checks_by_status` / `find_check_by_name`
98
+ - `get_check_status` - Detailed status with recent signals
99
+ - `get_check_uptime` - Uptime percentage with daily buckets
100
+ - `pause_check` / `resume_check`
101
+
102
+ ### Signals (Heartbeats)
103
+ - `send_heartbeat` - Send a success signal
104
+ - `send_failure_signal` - Report a failure
105
+ - `list_signals` - View signal history
106
+
107
+ ### Incidents
108
+ - `list_incidents` / `search_incidents` / `get_incident`
109
+ - `get_incident_timeline` - Incident history for a check
110
+ - `create_incident` / `acknowledge_incident` / `resolve_incident`
111
+ - `add_incident_note`
112
+
113
+ ### Deployments
114
+ - `create_deployment` - Start a deployment window (auto-pauses checks)
115
+ - `end_deployment` - End deployment and resume checks
116
+ - `list_deployments`
117
+
118
+ ### Dependencies
119
+ - `list_dependencies` / `get_dependency` / `create_dependency`
120
+ - `update_dependency_status`
121
+
122
+ ### Status Pages & Alerts
123
+ - `list_status_pages` / `create_status_page` / `update_status_page`
124
+ - `create_announcement`
125
+ - `list_alert_channels` / `create_alert_channel` / `update_alert_channel`
126
+ - `list_escalation_rules` / `create_escalation_rule` / `update_escalation_rule`
127
+
128
+ ## CLI Options
129
+
130
+ ```
131
+ npx @ionhour/mcp-server [options]
132
+
133
+ Options:
134
+ --api-key KEY IonHour API key (or set IONHOUR_API_KEY env var)
135
+ --base-url URL API base URL (default: https://app.failsignal.com)
136
+ --help, -h Show help
137
+ ```
138
+
139
+ ## How It Works
140
+
141
+ This package runs a local MCP server over **stdio** that proxies requests to the IonHour API. Your AI assistant communicates with this local server, which forwards tool calls to your IonHour workspace.
142
+
143
+ ```
144
+ AI Assistant <--stdio--> @ionhour/mcp-server <--HTTPS--> IonHour API
145
+ ```
146
+
147
+ ## Requirements
148
+
149
+ - Node.js >= 18
150
+ - An IonHour account with an API key
151
+
152
+ ## License
153
+
154
+ MIT
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@ionhour/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "IonHour MCP Server -- connect AI assistants to your uptime monitoring workspace",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "ionhour-mcp": "./src/bin.js"
8
+ },
9
+ "main": "./src/index.js",
10
+ "types": "./src/index.d.ts",
11
+ "type": "module",
12
+ "engines": {
13
+ "node": ">=18"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "ionhour",
19
+ "monitoring",
20
+ "uptime"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/ionhour/ionhour",
25
+ "directory": "libs/mcp-server"
26
+ },
27
+ "homepage": "https://ionhour.com",
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "dependencies": {
32
+ "@modelcontextprotocol/sdk": "^1.26.0"
33
+ },
34
+ "module": "./src/index.js"
35
+ }
package/src/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/src/bin.js ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { startProxyServer, resolveConfig } from './index.js';
3
+ function parseArgs() {
4
+ const args = process.argv.slice(2);
5
+ const result = {};
6
+ for (let i = 0; i < args.length; i++) {
7
+ if (args[i] === '--api-key' && args[i + 1]) {
8
+ result.apiKey = args[++i];
9
+ }
10
+ else if (args[i] === '--base-url' && args[i + 1]) {
11
+ result.baseUrl = args[++i];
12
+ }
13
+ else if (args[i] === '--help' || args[i] === '-h') {
14
+ process.stderr.write(`
15
+ IonHour MCP Server v0.1.0
16
+
17
+ Connect AI assistants to your IonHour monitoring workspace.
18
+
19
+ Usage:
20
+ npx @ionhour/mcp-server [options]
21
+
22
+ Options:
23
+ --api-key KEY IonHour API key (or set IONHOUR_API_KEY env var)
24
+ --base-url URL IonHour API base URL (default: https://app.failsignal.com)
25
+ --help, -h Show this help message
26
+
27
+ Setup with Claude Code:
28
+ claude mcp add ionhour -- npx @ionhour/mcp-server
29
+
30
+ Environment Variables:
31
+ IONHOUR_API_KEY API key for authentication
32
+ IONHOUR_BASE_URL Base URL override
33
+ `);
34
+ process.exit(0);
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ async function main() {
40
+ try {
41
+ const args = parseArgs();
42
+ const config = resolveConfig(args);
43
+ await startProxyServer(config);
44
+ }
45
+ catch (error) {
46
+ process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
47
+ process.exit(1);
48
+ }
49
+ }
50
+ main();
51
+ //# sourceMappingURL=bin.js.map
package/src/bin.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../../../libs/mcp-server/src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7D,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAA0C,EAAE,CAAC;IAEzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7B,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;CAmB1B,CAAC,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CACrE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
package/src/index.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export interface IonHourMcpConfig {
2
+ apiKey: string;
3
+ baseUrl: string;
4
+ }
5
+ /**
6
+ * Resolve configuration from explicit overrides, environment variables, or defaults.
7
+ * Throws if no API key is available from any source.
8
+ */
9
+ export declare function resolveConfig(overrides?: Partial<IonHourMcpConfig>): IonHourMcpConfig;
10
+ /**
11
+ * Start the stdio-to-HTTP MCP proxy server.
12
+ *
13
+ * 1. Connects to the remote IonHour MCP endpoint as a client
14
+ * 2. Exposes an MCP server over stdio
15
+ * 3. Proxies all tool/resource/prompt requests to the remote endpoint
16
+ */
17
+ export declare function startProxyServer(config: IonHourMcpConfig): Promise<void>;
package/src/index.js ADDED
@@ -0,0 +1,115 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
+ import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
6
+ /**
7
+ * Resolve configuration from explicit overrides, environment variables, or defaults.
8
+ * Throws if no API key is available from any source.
9
+ */
10
+ export function resolveConfig(overrides) {
11
+ const apiKey = overrides?.apiKey || process.env['IONHOUR_API_KEY'];
12
+ if (!apiKey) {
13
+ throw new Error('IonHour API key is required. Set IONHOUR_API_KEY environment variable or pass --api-key flag.');
14
+ }
15
+ return {
16
+ apiKey,
17
+ baseUrl: overrides?.baseUrl ||
18
+ process.env['IONHOUR_BASE_URL'] ||
19
+ 'https://app.failsignal.com',
20
+ };
21
+ }
22
+ /**
23
+ * Create an MCP Client connected to the remote IonHour API endpoint.
24
+ */
25
+ async function createRemoteClient(config) {
26
+ const transport = new StreamableHTTPClientTransport(new URL(`${config.baseUrl}/mcp`), {
27
+ requestInit: {
28
+ headers: {
29
+ Authorization: `Bearer ${config.apiKey}`,
30
+ },
31
+ },
32
+ });
33
+ const client = new Client({ name: 'ionhour-mcp-proxy', version: '0.1.0' });
34
+ await client.connect(transport);
35
+ return client;
36
+ }
37
+ /**
38
+ * Start the stdio-to-HTTP MCP proxy server.
39
+ *
40
+ * 1. Connects to the remote IonHour MCP endpoint as a client
41
+ * 2. Exposes an MCP server over stdio
42
+ * 3. Proxies all tool/resource/prompt requests to the remote endpoint
43
+ */
44
+ export async function startProxyServer(config) {
45
+ let remoteClient;
46
+ try {
47
+ remoteClient = await createRemoteClient(config);
48
+ }
49
+ catch (error) {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ process.stderr.write(`Failed to connect to IonHour API at ${config.baseUrl}/mcp: ${message}\n`);
52
+ process.exit(1);
53
+ }
54
+ const server = new Server({ name: 'ionhour', version: '0.1.0' }, {
55
+ capabilities: {
56
+ tools: {},
57
+ resources: {},
58
+ prompts: {},
59
+ },
60
+ });
61
+ // Proxy tools/list
62
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
63
+ const result = await remoteClient.listTools();
64
+ return { tools: result.tools };
65
+ });
66
+ // Proxy tools/call
67
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
68
+ const result = await remoteClient.callTool({
69
+ name: request.params.name,
70
+ arguments: request.params.arguments,
71
+ });
72
+ return result;
73
+ });
74
+ // Proxy resources/list
75
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
76
+ try {
77
+ const result = await remoteClient.listResources();
78
+ return { resources: result.resources };
79
+ }
80
+ catch {
81
+ return { resources: [] };
82
+ }
83
+ });
84
+ // Proxy resources/read
85
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
86
+ const result = await remoteClient.readResource({
87
+ uri: request.params.uri,
88
+ });
89
+ return result;
90
+ });
91
+ // Proxy prompts/list
92
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
93
+ try {
94
+ const result = await remoteClient.listPrompts();
95
+ return { prompts: result.prompts };
96
+ }
97
+ catch {
98
+ return { prompts: [] };
99
+ }
100
+ });
101
+ // Proxy prompts/get
102
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
103
+ const result = await remoteClient.getPrompt({
104
+ name: request.params.name,
105
+ arguments: request.params.arguments,
106
+ });
107
+ return result;
108
+ });
109
+ // Connect local server to stdio transport
110
+ const transport = new StdioServerTransport();
111
+ await server.connect(transport);
112
+ // Log to stderr so stdout remains clean for MCP JSON-RPC protocol
113
+ process.stderr.write('IonHour MCP server started (stdio proxy mode)\n');
114
+ }
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/mcp-server/src/index.ts"],"names":[],"mappings":"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"}