@hapticpaper/mcp-server 1.0.38 → 1.0.41

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.
@@ -0,0 +1,7 @@
1
+ export const REQUIRED_SCOPES = [
2
+ 'tasks:read',
3
+ 'tasks:write',
4
+ 'workers:read',
5
+ 'account:read',
6
+ 'account:write'
7
+ ];
package/dist/index.js CHANGED
@@ -13,9 +13,11 @@ import path from 'node:path';
13
13
  import jwt from 'jsonwebtoken';
14
14
  import { HapticPaperClient } from "./client/hapticPaperClient.js";
15
15
  import { CANONICAL_WIDGET_RESOURCES, LEGACY_WIDGET_RESOURCES } from "./constants/widget.js";
16
- import { registerAllTools } from "./tools/index.js";
16
+ import { registerAllTools, ALL_TOOL_SCOPES } from "./tools/index.js";
17
17
  import { registerAllResources } from "./resources/index.js";
18
18
  import { TokenManager, MCPOAuthHandler } from "./auth/oauth.js";
19
+ // REQUIRED_SCOPES is now deprecated in favor of ALL_TOOL_SCOPES
20
+ // import { REQUIRED_SCOPES } from "./constants/scopes.js";
19
21
  dotenv.config();
20
22
  async function main() {
21
23
  const args = process.argv.slice(2);
@@ -42,7 +44,7 @@ async function main() {
42
44
  process.exit(1);
43
45
  }
44
46
  }
45
- function registerWidgetTemplate(server) {
47
+ function registerWidgetTemplate(server, resourceBaseUrlOrigin) {
46
48
  // The widget bundle is built by packages/mcp-server/web and inlined into the HTML template.
47
49
  const widgetBundlePath = path.resolve(process.cwd(), 'web', 'dist', 'widget.js');
48
50
  if (!fs.existsSync(widgetBundlePath)) {
@@ -98,14 +100,15 @@ ${widgetJs}
98
100
  registerWidgetResource(name, uri);
99
101
  }
100
102
  }
101
- function createMcpServer(client) {
103
+ function createMcpServer(client, resourceBaseUrlOrigin) {
102
104
  const server = new McpServer({
103
105
  name: "haptic-paper",
104
106
  version: "1.0.0"
105
107
  });
106
- registerWidgetTemplate(server);
108
+ registerWidgetTemplate(server, resourceBaseUrlOrigin);
107
109
  registerAllTools(server, client);
108
110
  registerAllResources(server, client);
111
+ const scopesSupported = [...ALL_TOOL_SCOPES];
109
112
  return server;
110
113
  }
111
114
  const transportType = process.env.MCP_TRANSPORT || 'stdio';
@@ -117,7 +120,7 @@ ${widgetJs}
117
120
  authorizationUrl: process.env.AUTH_URL || 'https://hh.hapticpaper.com/oauth/authorize',
118
121
  tokenUrl: process.env.TOKEN_URL || 'https://hh.hapticpaper.com/api/v1/oauth/token',
119
122
  redirectUri: 'http://127.0.0.1/callback',
120
- scopes: ['tasks:read', 'tasks:write', 'workers:read', 'account:read']
123
+ scopes: [...ALL_TOOL_SCOPES]
121
124
  });
122
125
  const tokens = await auth.authenticate();
123
126
  await tokenManager.saveTokens(tokens);
@@ -141,6 +144,23 @@ ${widgetJs}
141
144
  console.error('Token expired, re-authenticating...');
142
145
  return runOAuthFlow();
143
146
  }
147
+ // Check for required scopes
148
+ try {
149
+ const decoded = jwt.decode(tokens.access_token);
150
+ if (decoded && typeof decoded === 'object') {
151
+ const tokenScopes = decoded.scope?.split(' ') || [];
152
+ const tokenScopeSet = new Set(tokenScopes);
153
+ const missingScopes = ALL_TOOL_SCOPES.filter(s => !tokenScopeSet.has(s));
154
+ if (missingScopes.length > 0) {
155
+ console.error(`Stored token missing scopes: ${missingScopes.join(', ')}. Re-authenticating...`);
156
+ return runOAuthFlow();
157
+ }
158
+ }
159
+ }
160
+ catch (e) {
161
+ console.error('Error validating token scopes, re-authenticating...', e);
162
+ return runOAuthFlow();
163
+ }
144
164
  return tokens.access_token;
145
165
  }
146
166
  // 3. No token - auto-trigger OAuth
@@ -405,7 +425,7 @@ ${widgetJs}
405
425
  delete transports[transport.sessionId];
406
426
  }
407
427
  };
408
- const server = createMcpServer(client);
428
+ const server = createMcpServer(client, resourceServerUrl.origin);
409
429
  await server.connect(transport);
410
430
  }
411
431
  else {
@@ -441,7 +461,7 @@ ${widgetJs}
441
461
  }
442
462
  else {
443
463
  const transport = new StdioServerTransport();
444
- const server = createMcpServer(client);
464
+ const server = createMcpServer(client, 'https://hh.hapticpaper.com');
445
465
  await server.connect(transport);
446
466
  console.error('MCP Server running on stdio');
447
467
  }
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { requireScopes } from "../auth/access.js";
3
3
  import { HAPTICPAPER_WIDGET_URI } from "../constants/widget.js";
4
+ export const ACCOUNT_TOOL_SCOPES = ['account:read', 'account:write'];
4
5
  import { handleToolError } from "./errorHandler.js";
5
6
  function oauthSecuritySchemes(scopes) {
6
7
  return [
@@ -1,9 +1,17 @@
1
- import { registerTasksTools } from "./tasks.js";
2
- import { registerWorkerTools } from "./workers.js";
3
- import { registerAccountTools } from "./account.js";
1
+ import { registerTasksTools, TASKS_TOOL_SCOPES } from "./tasks.js";
2
+ import { registerWorkerTools, WORKERS_TOOL_SCOPES } from "./workers.js";
3
+ import { registerAccountTools, ACCOUNT_TOOL_SCOPES } from "./account.js";
4
4
  import { registerQualificationTools } from "./qualification.js";
5
5
  import { registerGeneralTools } from "./general.js";
6
- import { registerMessagesTools } from "./messages.js";
6
+ import { registerMessagesTools, MESSAGES_TOOL_SCOPES } from "./messages.js";
7
+ // Aggregate all scopes from tools
8
+ export const ALL_TOOL_SCOPES = [
9
+ ...TASKS_TOOL_SCOPES,
10
+ ...WORKERS_TOOL_SCOPES,
11
+ ...ACCOUNT_TOOL_SCOPES,
12
+ ...MESSAGES_TOOL_SCOPES,
13
+ // Add other tool scopes here as they are defined
14
+ ];
7
15
  export function registerAllTools(server, client) {
8
16
  registerTasksTools(server, client);
9
17
  registerWorkerTools(server, client);
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { requireScopes } from "../auth/access.js";
3
3
  import { HAPTICPAPER_WIDGET_URI } from "../constants/widget.js";
4
+ export const MESSAGES_TOOL_SCOPES = ['messages:read', 'messages:write'];
4
5
  function oauthSecuritySchemes(scopes) {
5
6
  return [
6
7
  { type: 'oauth2', scopes },
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { requireScopes } from "../auth/access.js";
3
3
  import { HAPTICPAPER_WIDGET_URI } from "../constants/widget.js";
4
4
  import crypto from 'node:crypto';
5
+ export const TASKS_TOOL_SCOPES = ['tasks:read', 'tasks:write'];
5
6
  // --- Shared Helpers ---
6
7
  function stableSessionId(prefix, value) {
7
8
  const raw = value ?? 'unknown';
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { requireScopes } from "../auth/access.js";
3
3
  import { HAPTICPAPER_WIDGET_URI } from "../constants/widget.js";
4
4
  import crypto from 'node:crypto';
5
+ export const WORKERS_TOOL_SCOPES = ['workers:read', 'workers:write'];
5
6
  // --- Shared Helpers ---
6
7
  function stableSessionId(prefix, value) {
7
8
  const raw = value ?? 'unknown';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hapticpaper/mcp-server",
3
3
  "mcpName": "com.hapticpaper/mcp",
4
- "version": "1.0.38",
4
+ "version": "1.0.41",
5
5
  "description": "Official MCP Server for Haptic Paper - Connect your account to create human tasks from agentic pipelines.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
package/server.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "subfolder": "packages/mcp-server"
26
26
  },
27
27
  "websiteUrl": "https://hapticpaper.com/developer",
28
- "version": "1.0.38",
28
+ "version": "1.0.41",
29
29
  "remotes": [
30
30
  {
31
31
  "type": "streamable-http",
@@ -37,7 +37,7 @@
37
37
  "registryType": "npm",
38
38
  "registryBaseUrl": "https://registry.npmjs.org",
39
39
  "identifier": "@hapticpaper/mcp-server",
40
- "version": "1.0.38",
40
+ "version": "1.0.41",
41
41
  "transport": {
42
42
  "type": "stdio"
43
43
  },