@askmesh/mcp 0.11.2 → 0.12.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.
@@ -11,9 +11,22 @@ export declare class AutoResponder {
11
11
  agentType: string;
12
12
  allowedScopes: string[];
13
13
  }): void;
14
+ /**
15
+ * Filter scopes by the requester's role.
16
+ *
17
+ * Scopes can be encoded with a minimum-role prefix:
18
+ * "code" → all members
19
+ * "lead:db-schema" → lead, admin, owner only
20
+ * "admin:db-data" → admin, owner only
21
+ * "owner:secrets" → owner only
22
+ *
23
+ * Returns the bare scope names that this requester is allowed to use.
24
+ */
25
+ private filterScopesByRole;
14
26
  /**
15
27
  * Build a scope-aware extension to the system prompt.
16
28
  * Only applies for server agents — dev/ci agents are unrestricted.
29
+ * `requesterRole` is used to filter role-tiered scopes per request.
17
30
  */
18
31
  private scopePrompt;
19
32
  /**
@@ -32,23 +32,62 @@ export class AutoResponder {
32
32
  setProfile(profile) {
33
33
  this.profile = profile;
34
34
  }
35
+ /**
36
+ * Filter scopes by the requester's role.
37
+ *
38
+ * Scopes can be encoded with a minimum-role prefix:
39
+ * "code" → all members
40
+ * "lead:db-schema" → lead, admin, owner only
41
+ * "admin:db-data" → admin, owner only
42
+ * "owner:secrets" → owner only
43
+ *
44
+ * Returns the bare scope names that this requester is allowed to use.
45
+ */
46
+ filterScopesByRole(rawScopes, requesterRole) {
47
+ const ROLE_RANK = { member: 1, lead: 2, admin: 3, owner: 4 };
48
+ const requesterRank = requesterRole ? (ROLE_RANK[requesterRole] || 0) : 0;
49
+ const result = [];
50
+ for (const raw of rawScopes) {
51
+ const idx = raw.indexOf(':');
52
+ if (idx === -1) {
53
+ // No prefix → available to everyone
54
+ result.push(raw);
55
+ continue;
56
+ }
57
+ const minRole = raw.slice(0, idx);
58
+ const scope = raw.slice(idx + 1);
59
+ const minRank = ROLE_RANK[minRole];
60
+ if (!minRank) {
61
+ // Unknown prefix → treat as plain scope (e.g. "http:something")
62
+ result.push(raw);
63
+ continue;
64
+ }
65
+ if (requesterRank >= minRank) {
66
+ result.push(scope);
67
+ }
68
+ }
69
+ return result;
70
+ }
35
71
  /**
36
72
  * Build a scope-aware extension to the system prompt.
37
73
  * Only applies for server agents — dev/ci agents are unrestricted.
74
+ * `requesterRole` is used to filter role-tiered scopes per request.
38
75
  */
39
- scopePrompt() {
76
+ scopePrompt(requesterRole = null) {
40
77
  if (!this.profile || this.profile.agentType !== 'server')
41
78
  return '';
42
- const scopes = this.profile.allowedScopes;
43
- if (!scopes || scopes.length === 0) {
79
+ const allScopes = this.profile.allowedScopes || [];
80
+ const scopes = this.filterScopesByRole(allScopes, requesterRole);
81
+ const roleHint = requesterRole ? ` (requester role: ${requesterRole})` : ' (requester role: unknown)';
82
+ if (scopes.length === 0) {
44
83
  return [
45
84
  '',
46
- 'SERVER AGENT — RESTRICTIVE MODE:',
47
- 'No allowed scopes have been declared. Refuse to share any project content.',
48
- 'Reply with: "This is a restricted server agent. Please ask the human owner directly."',
85
+ `SERVER AGENT — RESTRICTIVE MODE${roleHint}:`,
86
+ 'No allowed scopes apply for this requester. Refuse to share any project content.',
87
+ 'Reply with: "This server agent is not authorized to share information at your role level."',
49
88
  ].join('\n');
50
89
  }
51
- const lines = ['', 'SERVER AGENT — ALLOWED SCOPES:'];
90
+ const lines = ['', `SERVER AGENT — ALLOWED SCOPES${roleHint}:`];
52
91
  lines.push('You are a restricted server agent. You may ONLY share information that falls within these scopes:');
53
92
  for (const s of scopes) {
54
93
  lines.push(` • ${s}`);
@@ -102,7 +141,7 @@ export class AutoResponder {
102
141
  if (this.mcpServer) {
103
142
  try {
104
143
  const context = readLocalContext();
105
- const scopeRules = this.scopePrompt();
144
+ const scopeRules = this.scopePrompt(request.fromUserRole || null);
106
145
  const result = (await this.mcpServer.request({
107
146
  method: 'sampling/createMessage',
108
147
  params: {
@@ -181,7 +220,7 @@ export class AutoResponder {
181
220
  }
182
221
  async callAnthropicAPI(apiKey, request, context) {
183
222
  const model = process.env.ANTHROPIC_MODEL || 'claude-sonnet-4-20250514';
184
- const fullSystem = SYSTEM_PROMPT + this.scopePrompt();
223
+ const fullSystem = SYSTEM_PROMPT + this.scopePrompt(request.fromUserRole || null);
185
224
  const response = await fetch('https://api.anthropic.com/v1/messages', {
186
225
  method: 'POST',
187
226
  headers: {
@@ -29,6 +29,7 @@ export declare class AskMeshClient {
29
29
  id: number;
30
30
  fromAgentId: number;
31
31
  fromUsername: string;
32
+ fromUserRole?: string | null;
32
33
  question: string;
33
34
  context: string | null;
34
35
  status: string;
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ const TOKEN = process.env.ASKMESH_TOKEN;
11
11
  const URL = process.env.ASKMESH_URL || 'https://api.askmesh.dev';
12
12
  const server = new McpServer({
13
13
  name: 'askmesh',
14
- version: '0.11.2',
14
+ version: '0.12.0',
15
15
  });
16
16
  if (!TOKEN) {
17
17
  // No token — start in setup-only mode
@@ -61,7 +61,8 @@ else {
61
61
  await autoResponder.handleRequest({
62
62
  id: req.id,
63
63
  fromAgentId: req.fromAgentId,
64
- fromUsername: `agent#${req.fromAgentId}`,
64
+ fromUsername: req.fromUsername || `agent#${req.fromAgentId}`,
65
+ fromUserRole: req.fromUserRole || null,
65
66
  question: req.question,
66
67
  context: req.context,
67
68
  });
@@ -2,6 +2,7 @@ export interface IncomingRequest {
2
2
  id: number;
3
3
  fromAgentId: number;
4
4
  fromUsername: string;
5
+ fromUserRole?: string | null;
5
6
  question: string;
6
7
  context: string | null;
7
8
  }
@@ -282,7 +282,7 @@ Si l'utilisateur n'a pas encore de compte, dirige-le vers https://askmesh.dev po
282
282
  return text('Action inconnue.');
283
283
  });
284
284
  }
285
- const CURRENT_VERSION = '0.11.2';
285
+ const CURRENT_VERSION = '0.12.0';
286
286
  async function checkUpdateAndSetup() {
287
287
  const lines = [];
288
288
  lines.push(`Version actuelle : ${CURRENT_VERSION}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askmesh/mcp",
3
- "version": "0.11.2",
3
+ "version": "0.12.0",
4
4
  "description": "AskMesh MCP server — connect your AI coding agent to your team's mesh network",
5
5
  "type": "module",
6
6
  "bin": {