acuity-mcp-server 1.0.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 +541 -0
- package/dist/auth/device-flow.d.ts +46 -0
- package/dist/auth/device-flow.d.ts.map +1 -0
- package/dist/auth/device-flow.js +141 -0
- package/dist/auth/device-flow.js.map +1 -0
- package/dist/auth/http-auth.d.ts +25 -0
- package/dist/auth/http-auth.d.ts.map +1 -0
- package/dist/auth/http-auth.js +101 -0
- package/dist/auth/http-auth.js.map +1 -0
- package/dist/auth/jwt-validator.d.ts +20 -0
- package/dist/auth/jwt-validator.d.ts.map +1 -0
- package/dist/auth/jwt-validator.js +83 -0
- package/dist/auth/jwt-validator.js.map +1 -0
- package/dist/auth/token-storage.d.ts +88 -0
- package/dist/auth/token-storage.d.ts.map +1 -0
- package/dist/auth/token-storage.js +273 -0
- package/dist/auth/token-storage.js.map +1 -0
- package/dist/clients/hasura-client.d.ts +33 -0
- package/dist/clients/hasura-client.d.ts.map +1 -0
- package/dist/clients/hasura-client.js +79 -0
- package/dist/clients/hasura-client.js.map +1 -0
- package/dist/config/environments.d.ts +51 -0
- package/dist/config/environments.d.ts.map +1 -0
- package/dist/config/environments.js +183 -0
- package/dist/config/environments.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +593 -0
- package/dist/index.js.map +1 -0
- package/dist/server/http-server.d.ts +14 -0
- package/dist/server/http-server.d.ts.map +1 -0
- package/dist/server/http-server.js +167 -0
- package/dist/server/http-server.js.map +1 -0
- package/dist/server/mcp-core.d.ts +12 -0
- package/dist/server/mcp-core.d.ts.map +1 -0
- package/dist/server/mcp-core.js +200 -0
- package/dist/server/mcp-core.js.map +1 -0
- package/dist/tools/acuity-init.d.ts +84 -0
- package/dist/tools/acuity-init.d.ts.map +1 -0
- package/dist/tools/acuity-init.js +239 -0
- package/dist/tools/acuity-init.js.map +1 -0
- package/dist/tools/get-dashboard-summary.d.ts +96 -0
- package/dist/tools/get-dashboard-summary.d.ts.map +1 -0
- package/dist/tools/get-dashboard-summary.js +264 -0
- package/dist/tools/get-dashboard-summary.js.map +1 -0
- package/dist/tools/get-issue.d.ts +62 -0
- package/dist/tools/get-issue.d.ts.map +1 -0
- package/dist/tools/get-issue.js +150 -0
- package/dist/tools/get-issue.js.map +1 -0
- package/dist/tools/get-lesson-learned.d.ts +53 -0
- package/dist/tools/get-lesson-learned.d.ts.map +1 -0
- package/dist/tools/get-lesson-learned.js +117 -0
- package/dist/tools/get-lesson-learned.js.map +1 -0
- package/dist/tools/get-lookup-values.d.ts +41 -0
- package/dist/tools/get-lookup-values.d.ts.map +1 -0
- package/dist/tools/get-lookup-values.js +127 -0
- package/dist/tools/get-lookup-values.js.map +1 -0
- package/dist/tools/get-project.d.ts +131 -0
- package/dist/tools/get-project.d.ts.map +1 -0
- package/dist/tools/get-project.js +340 -0
- package/dist/tools/get-project.js.map +1 -0
- package/dist/tools/get-risk.d.ts +65 -0
- package/dist/tools/get-risk.d.ts.map +1 -0
- package/dist/tools/get-risk.js +173 -0
- package/dist/tools/get-risk.js.map +1 -0
- package/dist/tools/get-status-reports.d.ts +46 -0
- package/dist/tools/get-status-reports.d.ts.map +1 -0
- package/dist/tools/get-status-reports.js +151 -0
- package/dist/tools/get-status-reports.js.map +1 -0
- package/dist/tools/init-auth.d.ts +47 -0
- package/dist/tools/init-auth.d.ts.map +1 -0
- package/dist/tools/init-auth.js +213 -0
- package/dist/tools/init-auth.js.map +1 -0
- package/dist/tools/list-issues.d.ts +134 -0
- package/dist/tools/list-issues.d.ts.map +1 -0
- package/dist/tools/list-issues.js +285 -0
- package/dist/tools/list-issues.js.map +1 -0
- package/dist/tools/list-lessons-learned.d.ts +79 -0
- package/dist/tools/list-lessons-learned.d.ts.map +1 -0
- package/dist/tools/list-lessons-learned.js +155 -0
- package/dist/tools/list-lessons-learned.js.map +1 -0
- package/dist/tools/list-projects.d.ts +200 -0
- package/dist/tools/list-projects.d.ts.map +1 -0
- package/dist/tools/list-projects.js +396 -0
- package/dist/tools/list-projects.js.map +1 -0
- package/dist/tools/list-risks.d.ts +166 -0
- package/dist/tools/list-risks.d.ts.map +1 -0
- package/dist/tools/list-risks.js +356 -0
- package/dist/tools/list-risks.js.map +1 -0
- package/dist/tools/search-projects.d.ts +90 -0
- package/dist/tools/search-projects.d.ts.map +1 -0
- package/dist/tools/search-projects.js +191 -0
- package/dist/tools/search-projects.js.map +1 -0
- package/dist/utils/formatters.d.ts +12 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +28 -0
- package/dist/utils/formatters.js.map +1 -0
- package/openapi.yaml +194 -0
- package/package.json +68 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: get_risk
|
|
3
|
+
* Returns full details for a single risk by ID
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Enum conversion: DB integers → human-readable strings
|
|
7
|
+
* - Hasura relationships: returns resolved names instead of IDs
|
|
8
|
+
*/
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Enum Mappings
|
|
11
|
+
// ============================================================================
|
|
12
|
+
const DB_TO_STATUS = {
|
|
13
|
+
0: 'open',
|
|
14
|
+
1: 'closed',
|
|
15
|
+
2: 'realized'
|
|
16
|
+
};
|
|
17
|
+
const DB_TO_PRIORITY = {
|
|
18
|
+
0: 'very_low',
|
|
19
|
+
1: 'low',
|
|
20
|
+
2: 'medium',
|
|
21
|
+
3: 'high',
|
|
22
|
+
4: 'critical'
|
|
23
|
+
};
|
|
24
|
+
const DB_TO_RISK_RESPONSE = {
|
|
25
|
+
0: 'mitigate',
|
|
26
|
+
1: 'accept',
|
|
27
|
+
2: 'avoid',
|
|
28
|
+
3: 'watch',
|
|
29
|
+
4: 'transfer'
|
|
30
|
+
};
|
|
31
|
+
const DB_TO_SEVERITY = {
|
|
32
|
+
0: 'very_low',
|
|
33
|
+
1: 'low',
|
|
34
|
+
2: 'medium',
|
|
35
|
+
3: 'high',
|
|
36
|
+
4: 'very_high'
|
|
37
|
+
};
|
|
38
|
+
const DB_TO_LIKELIHOOD = {
|
|
39
|
+
0: 'very_low',
|
|
40
|
+
1: 'low',
|
|
41
|
+
2: 'medium',
|
|
42
|
+
3: 'high',
|
|
43
|
+
4: 'very_high'
|
|
44
|
+
};
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Helper Functions
|
|
47
|
+
// ============================================================================
|
|
48
|
+
function fromDbValue(value, mapping) {
|
|
49
|
+
if (value === null || value === undefined)
|
|
50
|
+
return null;
|
|
51
|
+
return mapping[value] ?? null;
|
|
52
|
+
}
|
|
53
|
+
function transformRisk(raw) {
|
|
54
|
+
return {
|
|
55
|
+
id: raw.id,
|
|
56
|
+
risk_id: raw.risk_id,
|
|
57
|
+
name: raw.name,
|
|
58
|
+
description: raw.description,
|
|
59
|
+
notes: raw.notes,
|
|
60
|
+
hyperlinks: raw.hyperlinks,
|
|
61
|
+
status: fromDbValue(raw.status, DB_TO_STATUS) ?? 'open',
|
|
62
|
+
priority: fromDbValue(raw.priority, DB_TO_PRIORITY) ?? 'low',
|
|
63
|
+
severity: fromDbValue(raw.severity, DB_TO_SEVERITY) ?? 'very_low',
|
|
64
|
+
likelihood: fromDbValue(raw.likelihood, DB_TO_LIKELIHOOD) ?? 'very_low',
|
|
65
|
+
risk_response: fromDbValue(raw.risk_response, DB_TO_RISK_RESPONSE) ?? 'mitigate',
|
|
66
|
+
impact_score: raw.impact_score ?? 0,
|
|
67
|
+
response_plan: raw.response_plan,
|
|
68
|
+
created_at: raw.created_at,
|
|
69
|
+
updated_at: raw.updated_at,
|
|
70
|
+
project: raw.project,
|
|
71
|
+
owner: raw.company_project_resource
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// GraphQL Query
|
|
76
|
+
// ============================================================================
|
|
77
|
+
const GET_RISK_QUERY = `
|
|
78
|
+
query GetRisk($where: risks_bool_exp!) {
|
|
79
|
+
risks(where: $where, limit: 1) {
|
|
80
|
+
id
|
|
81
|
+
risk_id
|
|
82
|
+
name
|
|
83
|
+
description
|
|
84
|
+
notes
|
|
85
|
+
hyperlinks
|
|
86
|
+
status
|
|
87
|
+
priority
|
|
88
|
+
severity
|
|
89
|
+
likelihood
|
|
90
|
+
risk_response
|
|
91
|
+
impact_score
|
|
92
|
+
response_plan
|
|
93
|
+
created_at
|
|
94
|
+
updated_at
|
|
95
|
+
|
|
96
|
+
project { id name }
|
|
97
|
+
company_project_resource { id name }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Main Handler
|
|
103
|
+
// ============================================================================
|
|
104
|
+
export async function getRisk(input, hasuraClient) {
|
|
105
|
+
const { risk_id, risk_number } = input;
|
|
106
|
+
// Validate input
|
|
107
|
+
if (risk_id === undefined && risk_number === undefined) {
|
|
108
|
+
return { risk: null };
|
|
109
|
+
}
|
|
110
|
+
// Build where clause
|
|
111
|
+
let whereClause;
|
|
112
|
+
if (risk_id !== undefined) {
|
|
113
|
+
whereClause = { id: { _eq: risk_id } };
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
whereClause = { risk_id: { _eq: risk_number } };
|
|
117
|
+
}
|
|
118
|
+
const result = await hasuraClient.query(GET_RISK_QUERY, {
|
|
119
|
+
where: whereClause
|
|
120
|
+
});
|
|
121
|
+
if (!result.risks || result.risks.length === 0) {
|
|
122
|
+
return { risk: null };
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
risk: transformRisk(result.risks[0])
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// Tool Definition
|
|
130
|
+
// ============================================================================
|
|
131
|
+
export const getRiskTool = {
|
|
132
|
+
name: 'get_risk',
|
|
133
|
+
description: `
|
|
134
|
+
Get full details for a single risk by ID.
|
|
135
|
+
|
|
136
|
+
Returns all risk information including:
|
|
137
|
+
- Identifiers: id (database), risk_id (human-readable number within company)
|
|
138
|
+
- Content: name, description, notes, hyperlinks, response_plan
|
|
139
|
+
- Classification: status, priority, severity, likelihood, risk_response
|
|
140
|
+
- Scoring: impact_score (severity × likelihood, range 1-25)
|
|
141
|
+
- Dates: created_at, updated_at
|
|
142
|
+
- Relationships: project { id, name }, owner { id, name }
|
|
143
|
+
|
|
144
|
+
SEARCH OPTIONS (provide one):
|
|
145
|
+
- risk_id: Database primary key (integer)
|
|
146
|
+
- risk_number: Human-readable risk number within company (e.g., 42)
|
|
147
|
+
|
|
148
|
+
ENUM VALUES:
|
|
149
|
+
- status: "open", "closed", "realized"
|
|
150
|
+
- priority: "very_low", "low", "medium", "high", "critical"
|
|
151
|
+
- severity: "very_low", "low", "medium", "high", "very_high"
|
|
152
|
+
- likelihood: "very_low", "low", "medium", "high", "very_high"
|
|
153
|
+
- risk_response: "mitigate", "accept", "avoid", "watch", "transfer"
|
|
154
|
+
|
|
155
|
+
EXAMPLES:
|
|
156
|
+
- Get by database ID: risk_id: 123
|
|
157
|
+
- Get by risk number: risk_number: 42
|
|
158
|
+
`.trim(),
|
|
159
|
+
inputSchema: {
|
|
160
|
+
type: 'object',
|
|
161
|
+
properties: {
|
|
162
|
+
risk_id: {
|
|
163
|
+
type: 'number',
|
|
164
|
+
description: 'Risk database ID (primary key)'
|
|
165
|
+
},
|
|
166
|
+
risk_number: {
|
|
167
|
+
type: 'number',
|
|
168
|
+
description: 'Human-readable risk number within company'
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=get-risk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-risk.js","sourceRoot":"","sources":["../../src/tools/get-risk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: get_status_reports
|
|
3
|
+
* Get status reports with optional filtering by project
|
|
4
|
+
*/
|
|
5
|
+
import type { HasuraClient } from '../clients/hasura-client.js';
|
|
6
|
+
export interface GetStatusReportsInput {
|
|
7
|
+
project_id?: number;
|
|
8
|
+
project_name?: string;
|
|
9
|
+
limit?: number;
|
|
10
|
+
offset?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get status reports handler
|
|
14
|
+
*/
|
|
15
|
+
export declare function getStatusReports(input: GetStatusReportsInput, hasuraClient: HasuraClient): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* MCP tool definition for get_status_reports
|
|
18
|
+
*/
|
|
19
|
+
export declare const getStatusReportsTool: {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: string;
|
|
24
|
+
properties: {
|
|
25
|
+
project_id: {
|
|
26
|
+
type: string;
|
|
27
|
+
description: string;
|
|
28
|
+
};
|
|
29
|
+
project_name: {
|
|
30
|
+
type: string;
|
|
31
|
+
description: string;
|
|
32
|
+
};
|
|
33
|
+
limit: {
|
|
34
|
+
type: string;
|
|
35
|
+
description: string;
|
|
36
|
+
default: number;
|
|
37
|
+
};
|
|
38
|
+
offset: {
|
|
39
|
+
type: string;
|
|
40
|
+
description: string;
|
|
41
|
+
default: number;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=get-status-reports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-status-reports.d.ts","sourceRoot":"","sources":["../../src/tools/get-status-reports.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsGD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,EAC5B,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDhC,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: get_status_reports
|
|
3
|
+
* Get status reports with optional filtering by project
|
|
4
|
+
*/
|
|
5
|
+
import { formatDate, divider } from '../utils/formatters.js';
|
|
6
|
+
/**
|
|
7
|
+
* Build GraphQL query for status reports
|
|
8
|
+
*/
|
|
9
|
+
function buildStatusReportsQuery(projectId, projectName) {
|
|
10
|
+
let whereConditions = '';
|
|
11
|
+
if (projectId) {
|
|
12
|
+
whereConditions = `where: { project_id: { _eq: ${projectId} } }`;
|
|
13
|
+
}
|
|
14
|
+
else if (projectName) {
|
|
15
|
+
// Case-insensitive search by project name
|
|
16
|
+
whereConditions = `where: { project: { name: { _ilike: "%${projectName}%" } } }`;
|
|
17
|
+
}
|
|
18
|
+
return `
|
|
19
|
+
query GetStatusReports($limit: Int!, $offset: Int!) {
|
|
20
|
+
status_reports(
|
|
21
|
+
${whereConditions}
|
|
22
|
+
order_by: { created_at: desc }
|
|
23
|
+
limit: $limit
|
|
24
|
+
offset: $offset
|
|
25
|
+
) {
|
|
26
|
+
id
|
|
27
|
+
summary
|
|
28
|
+
accomplishments
|
|
29
|
+
look_ahead
|
|
30
|
+
help_needed
|
|
31
|
+
created_at
|
|
32
|
+
updated_at
|
|
33
|
+
project {
|
|
34
|
+
id
|
|
35
|
+
name
|
|
36
|
+
}
|
|
37
|
+
user {
|
|
38
|
+
name
|
|
39
|
+
email
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
status_reports_aggregate(
|
|
44
|
+
${whereConditions}
|
|
45
|
+
) {
|
|
46
|
+
aggregate {
|
|
47
|
+
count
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Format status reports for display
|
|
55
|
+
*/
|
|
56
|
+
function formatStatusReports(reports, totalCount, hasMore) {
|
|
57
|
+
if (reports.length === 0) {
|
|
58
|
+
return 'No status reports found.';
|
|
59
|
+
}
|
|
60
|
+
const header = `Found ${totalCount} status report${totalCount !== 1 ? 's' : ''} total. Showing ${reports.length}.`;
|
|
61
|
+
const formatted = reports.map((report, idx) => {
|
|
62
|
+
return `
|
|
63
|
+
${divider()}
|
|
64
|
+
STATUS REPORT #${idx + 1} (ID: ${report.id})
|
|
65
|
+
${divider()}
|
|
66
|
+
|
|
67
|
+
Project: ${report.project.name} (ID: ${report.project.id})
|
|
68
|
+
Reported by: ${report.user?.name || 'Unknown'} ${report.user?.email ? `(${report.user.email})` : ''}
|
|
69
|
+
Date: ${formatDate(report.created_at)}
|
|
70
|
+
Last Updated: ${formatDate(report.updated_at)}
|
|
71
|
+
|
|
72
|
+
SUMMARY:
|
|
73
|
+
${report.summary || 'No summary provided'}
|
|
74
|
+
|
|
75
|
+
${report.accomplishments ? `ACCOMPLISHMENTS:\n${report.accomplishments}\n` : ''}
|
|
76
|
+
${report.look_ahead ? `LOOKING AHEAD:\n${report.look_ahead}\n` : ''}
|
|
77
|
+
${report.help_needed ? `HELP NEEDED:\n${report.help_needed}\n` : ''}
|
|
78
|
+
`.trim();
|
|
79
|
+
}).join('\n\n');
|
|
80
|
+
return `${header}\n\n${formatted}${hasMore ? '\n\n...(more reports available, use offset to see next page)' : ''}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get status reports handler
|
|
84
|
+
*/
|
|
85
|
+
export async function getStatusReports(input, hasuraClient) {
|
|
86
|
+
const { project_id, project_name, limit = 10, offset = 0 } = input;
|
|
87
|
+
// Build and execute GraphQL query
|
|
88
|
+
const query = buildStatusReportsQuery(project_id, project_name);
|
|
89
|
+
const result = await hasuraClient.query(query, {
|
|
90
|
+
limit,
|
|
91
|
+
offset
|
|
92
|
+
});
|
|
93
|
+
const totalCount = result.status_reports_aggregate.aggregate.count;
|
|
94
|
+
const hasMore = offset + result.status_reports.length < totalCount;
|
|
95
|
+
return formatStatusReports(result.status_reports, totalCount, hasMore);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* MCP tool definition for get_status_reports
|
|
99
|
+
*/
|
|
100
|
+
export const getStatusReportsTool = {
|
|
101
|
+
name: 'get_status_reports',
|
|
102
|
+
description: `
|
|
103
|
+
Get status reports with optional filtering by project ID or project name.
|
|
104
|
+
|
|
105
|
+
Returns detailed status report information:
|
|
106
|
+
- Summary of the report
|
|
107
|
+
- Accomplishments
|
|
108
|
+
- Looking ahead
|
|
109
|
+
- Help needed
|
|
110
|
+
- Project information (ID and name)
|
|
111
|
+
- Reporter information (name and email)
|
|
112
|
+
- Dates (created and updated)
|
|
113
|
+
|
|
114
|
+
Use this tool when users ask:
|
|
115
|
+
- "Show me all status reports"
|
|
116
|
+
- "Get status reports for project #123"
|
|
117
|
+
- "Show me status reports for project Auto Scrap"
|
|
118
|
+
- "What are the latest status updates?"
|
|
119
|
+
- "Show me recent status reports for [project name]"
|
|
120
|
+
|
|
121
|
+
You can filter by:
|
|
122
|
+
- project_id: Exact project ID (e.g., 123)
|
|
123
|
+
- project_name: Project name (case-insensitive, partial match, e.g., "Auto Scrap")
|
|
124
|
+
|
|
125
|
+
If no filters provided, returns all accessible status reports.
|
|
126
|
+
`.trim(),
|
|
127
|
+
inputSchema: {
|
|
128
|
+
type: 'object',
|
|
129
|
+
properties: {
|
|
130
|
+
project_id: {
|
|
131
|
+
type: 'number',
|
|
132
|
+
description: 'Filter by specific project ID'
|
|
133
|
+
},
|
|
134
|
+
project_name: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
description: 'Filter by project name (case-insensitive, partial match)'
|
|
137
|
+
},
|
|
138
|
+
limit: {
|
|
139
|
+
type: 'number',
|
|
140
|
+
description: 'Maximum number of reports to return (default: 10)',
|
|
141
|
+
default: 10
|
|
142
|
+
},
|
|
143
|
+
offset: {
|
|
144
|
+
type: 'number',
|
|
145
|
+
description: 'Number of reports to skip for pagination (default: 0)',
|
|
146
|
+
default: 0
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=get-status-reports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-status-reports.js","sourceRoot":"","sources":["../../src/tools/get-status-reports.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AA2B7D;;GAEG;AACH,SAAS,uBAAuB,CAAC,SAAkB,EAAE,WAAoB;IACvE,IAAI,eAAe,GAAG,EAAE,CAAC;IAEzB,IAAI,SAAS,EAAE,CAAC;QACd,eAAe,GAAG,+BAA+B,SAAS,MAAM,CAAC;IACnE,CAAC;SAAM,IAAI,WAAW,EAAE,CAAC;QACvB,0CAA0C;QAC1C,eAAe,GAAG,yCAAyC,WAAW,UAAU,CAAC;IACnF,CAAC;IAED,OAAO;;;UAGC,eAAe;;;;;;;;;;;;;;;;;;;;;;;UAuBf,eAAe;;;;;;;GAOtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,OAAuB,EAAE,UAAkB,EAAE,OAAgB;IACxF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,UAAU,iBAAiB,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,mBAAmB,OAAO,CAAC,MAAM,GAAG,CAAC;IAEnH,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QAC5C,OAAO;EACT,OAAO,EAAE;iBACM,GAAG,GAAG,CAAC,SAAS,MAAM,CAAC,EAAE;EACxC,OAAO,EAAE;;WAEA,MAAM,CAAC,OAAO,CAAC,IAAI,SAAS,MAAM,CAAC,OAAO,CAAC,EAAE;eACzC,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE;QAC3F,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC;gBACrB,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC;;;EAG3C,MAAM,CAAC,OAAO,IAAI,qBAAqB;;EAEvC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,qBAAqB,MAAM,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,EAAE;EAC7E,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE;EACjE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,iBAAiB,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,EAAE;KAC9D,CAAC,IAAI,EAAE,CAAC;IACX,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,OAAO,GAAG,MAAM,OAAO,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,8DAA8D,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACrH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAA4B,EAC5B,YAA0B;IAE1B,MAAM,EACJ,UAAU,EACV,YAAY,EACZ,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,CAAC,EACX,GAAG,KAAK,CAAC;IAEV,kCAAkC;IAClC,MAAM,KAAK,GAAG,uBAAuB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAGpC,KAAK,EAAE;QACR,KAAK;QACL,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,SAAS,CAAC,KAAK,CAAC;IACnE,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,UAAU,CAAC;IAEnE,OAAO,mBAAmB,CAAC,MAAM,CAAC,cAAc,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;GAwBZ,CAAC,IAAI,EAAE;IAER,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+BAA+B;aAC7C;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0DAA0D;aACxE;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,mDAAmD;gBAChE,OAAO,EAAE,EAAE;aACZ;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uDAAuD;gBACpE,OAAO,EAAE,CAAC;aACX;SACF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication initialization tool
|
|
3
|
+
* Allows users to authenticate via Claude by triggering Device Flow
|
|
4
|
+
*/
|
|
5
|
+
export declare const initAuthTool: {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
inputSchema: {
|
|
9
|
+
type: string;
|
|
10
|
+
properties: {};
|
|
11
|
+
required: never[];
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare const logoutTool: {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: string;
|
|
19
|
+
properties: {};
|
|
20
|
+
required: never[];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export declare const authStatusTool: {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: string;
|
|
28
|
+
properties: {};
|
|
29
|
+
required: never[];
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Login - Two-phase Device Flow
|
|
34
|
+
*
|
|
35
|
+
* Phase 1: Request device code, show to user, open browser
|
|
36
|
+
* Phase 2: Poll for token completion when user calls again
|
|
37
|
+
*/
|
|
38
|
+
export declare function initAuth(): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Handle logout - clears credentials and pending auth
|
|
41
|
+
*/
|
|
42
|
+
export declare function logout(): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Check auth status
|
|
45
|
+
*/
|
|
46
|
+
export declare function getAuthStatus(): Promise<string>;
|
|
47
|
+
//# sourceMappingURL=init-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-auth.d.ts","sourceRoot":"","sources":["../../src/tools/init-auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,eAAO,MAAM,YAAY;;;;;;;;CAQxB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;CAQtB,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;CAQ1B,CAAC;AAYF;;;;;GAKG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CA2DhD;AA2ED;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAS9C;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAuCrD"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication initialization tool
|
|
3
|
+
* Allows users to authenticate via Claude by triggering Device Flow
|
|
4
|
+
*/
|
|
5
|
+
import open from 'open';
|
|
6
|
+
import { requestDeviceCode, pollForToken } from '../auth/device-flow.js';
|
|
7
|
+
import { saveCredentials, loadCredentials, clearCredentials, tokenResponseToCredentials, savePendingDeviceCode, loadPendingDeviceCode, clearPendingDeviceCode, } from '../auth/token-storage.js';
|
|
8
|
+
import { getEnvironment } from '../config/environments.js';
|
|
9
|
+
export const initAuthTool = {
|
|
10
|
+
name: 'acuity_login',
|
|
11
|
+
description: 'Login to Acuity. Opens a browser for secure login. Wait for the login to complete.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {},
|
|
15
|
+
required: []
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
export const logoutTool = {
|
|
19
|
+
name: 'acuity_logout',
|
|
20
|
+
description: 'Logout from Acuity and clear stored credentials.',
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {},
|
|
24
|
+
required: []
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export const authStatusTool = {
|
|
28
|
+
name: 'acuity_auth_status',
|
|
29
|
+
description: 'Check current Acuity authentication status.',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {},
|
|
33
|
+
required: []
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
function getAuth0Config() {
|
|
37
|
+
const env = getEnvironment();
|
|
38
|
+
return {
|
|
39
|
+
domain: env.auth0Domain,
|
|
40
|
+
clientId: env.auth0ClientId,
|
|
41
|
+
audience: process.env.AUTH0_AUDIENCE,
|
|
42
|
+
scope: 'openid profile email offline_access',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Login - Two-phase Device Flow
|
|
47
|
+
*
|
|
48
|
+
* Phase 1: Request device code, show to user, open browser
|
|
49
|
+
* Phase 2: Poll for token completion when user calls again
|
|
50
|
+
*/
|
|
51
|
+
export async function initAuth() {
|
|
52
|
+
try {
|
|
53
|
+
// Check if already authenticated
|
|
54
|
+
const existingCreds = await loadCredentials();
|
|
55
|
+
if (existingCreds) {
|
|
56
|
+
const now = Math.floor(Date.now() / 1000);
|
|
57
|
+
if (existingCreds.expiresAt > now) {
|
|
58
|
+
return `Already authenticated as ${existingCreds.email || 'unknown user'}. Use acuity_logout first if you want to re-authenticate.`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const config = getAuth0Config();
|
|
62
|
+
// Check if there's a pending device code (Phase 2)
|
|
63
|
+
const pending = await loadPendingDeviceCode();
|
|
64
|
+
if (pending) {
|
|
65
|
+
return await completePendingAuth(config, pending);
|
|
66
|
+
}
|
|
67
|
+
// Phase 1: Request new device code
|
|
68
|
+
const deviceCodeResponse = await requestDeviceCode(config);
|
|
69
|
+
// Save pending device code for Phase 2
|
|
70
|
+
const now = Math.floor(Date.now() / 1000);
|
|
71
|
+
const pendingCode = {
|
|
72
|
+
deviceCode: deviceCodeResponse.device_code,
|
|
73
|
+
userCode: deviceCodeResponse.user_code,
|
|
74
|
+
verificationUri: deviceCodeResponse.verification_uri,
|
|
75
|
+
interval: deviceCodeResponse.interval,
|
|
76
|
+
expiresAt: now + deviceCodeResponse.expires_in,
|
|
77
|
+
};
|
|
78
|
+
await savePendingDeviceCode(pendingCode);
|
|
79
|
+
// Open browser - logout from Auth0 first to force fresh login
|
|
80
|
+
const returnUrl = `https://${config.domain}/activate?user_code=${deviceCodeResponse.user_code}`;
|
|
81
|
+
const logoutUrl = `https://${config.domain}/v2/logout?client_id=${config.clientId}&returnTo=${encodeURIComponent(returnUrl)}`;
|
|
82
|
+
try {
|
|
83
|
+
await open(logoutUrl);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Browser didn't open, will show manual instructions
|
|
87
|
+
}
|
|
88
|
+
// Return immediately with the code - user will call again after completing login
|
|
89
|
+
return `🔐 **Verification Code: ${deviceCodeResponse.user_code}**
|
|
90
|
+
|
|
91
|
+
A browser window is opening for login.
|
|
92
|
+
|
|
93
|
+
**Please verify this code matches what you see in the browser before confirming!**
|
|
94
|
+
|
|
95
|
+
After you complete the login in your browser, say **"continue login"** or call this tool again to complete authentication.
|
|
96
|
+
|
|
97
|
+
_Code expires in ${Math.floor(deviceCodeResponse.expires_in / 60)} minutes._`;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
await clearPendingDeviceCode(); // Clean up on error
|
|
102
|
+
return `❌ Login failed: ${message}. Please try again.`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Complete pending authentication (Phase 2)
|
|
107
|
+
*/
|
|
108
|
+
async function completePendingAuth(config, pending) {
|
|
109
|
+
try {
|
|
110
|
+
console.error(`[Auth] Checking pending authorization for code: ${pending.userCode}`);
|
|
111
|
+
const now = Math.floor(Date.now() / 1000);
|
|
112
|
+
const remainingTime = pending.expiresAt - now;
|
|
113
|
+
// Poll for token
|
|
114
|
+
const token = await pollForToken(config, pending.deviceCode, pending.interval, remainingTime, () => { } // No progress callback needed in MCP context
|
|
115
|
+
);
|
|
116
|
+
// Clear pending code
|
|
117
|
+
await clearPendingDeviceCode();
|
|
118
|
+
// Extract email from id_token
|
|
119
|
+
let email;
|
|
120
|
+
if (token.id_token) {
|
|
121
|
+
try {
|
|
122
|
+
const payload = JSON.parse(Buffer.from(token.id_token.split('.')[1], 'base64').toString());
|
|
123
|
+
email = payload.email || payload['https://acuity.com/email'] || payload['https://acuityppm.com/email'];
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Ignore parsing errors
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Save credentials
|
|
130
|
+
const credentials = tokenResponseToCredentials(token, email);
|
|
131
|
+
await saveCredentials(credentials);
|
|
132
|
+
const env = getEnvironment();
|
|
133
|
+
return `✅ **Login Successful!**
|
|
134
|
+
|
|
135
|
+
Environment: ${env.name}
|
|
136
|
+
Logged in as: ${email || 'unknown user'}
|
|
137
|
+
|
|
138
|
+
You can now use Acuity tools:
|
|
139
|
+
- "Show me my projects"
|
|
140
|
+
- "List active projects"
|
|
141
|
+
- "Get status reports"`;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
145
|
+
// Check if it's "authorization pending" - user hasn't completed yet
|
|
146
|
+
if (message.includes('authorization_pending') || message.includes('Authorization timed out')) {
|
|
147
|
+
const remaining = Math.floor((pending.expiresAt - Math.floor(Date.now() / 1000)) / 60);
|
|
148
|
+
if (remaining > 0) {
|
|
149
|
+
return `⏳ **Waiting for login...**
|
|
150
|
+
|
|
151
|
+
Your verification code: **${pending.userCode}**
|
|
152
|
+
|
|
153
|
+
Please complete the login in your browser, then call this tool again.
|
|
154
|
+
|
|
155
|
+
_Code expires in ${remaining} minutes._`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Real error or expired - clean up
|
|
159
|
+
await clearPendingDeviceCode();
|
|
160
|
+
return `❌ Login failed: ${message}. Please try again.`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Handle logout - clears credentials and pending auth
|
|
165
|
+
*/
|
|
166
|
+
export async function logout() {
|
|
167
|
+
const deletedCreds = await clearCredentials();
|
|
168
|
+
const deletedPending = await clearPendingDeviceCode();
|
|
169
|
+
if (deletedCreds || deletedPending) {
|
|
170
|
+
return '✅ Successfully logged out. Credentials removed from system keychain.';
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
return 'No credentials found. You are not logged in.';
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check auth status
|
|
178
|
+
*/
|
|
179
|
+
export async function getAuthStatus() {
|
|
180
|
+
// Check for pending auth first
|
|
181
|
+
const pending = await loadPendingDeviceCode();
|
|
182
|
+
if (pending) {
|
|
183
|
+
const now = Math.floor(Date.now() / 1000);
|
|
184
|
+
const remaining = Math.floor((pending.expiresAt - now) / 60);
|
|
185
|
+
return `⏳ **Login in progress...**
|
|
186
|
+
|
|
187
|
+
Your verification code: **${pending.userCode}**
|
|
188
|
+
|
|
189
|
+
Complete the login in your browser, then say "continue login".
|
|
190
|
+
|
|
191
|
+
_Code expires in ${remaining} minutes._`;
|
|
192
|
+
}
|
|
193
|
+
const creds = await loadCredentials();
|
|
194
|
+
if (!creds) {
|
|
195
|
+
return '❌ Not authenticated. Use "login to Acuity" to authenticate.';
|
|
196
|
+
}
|
|
197
|
+
const now = Math.floor(Date.now() / 1000);
|
|
198
|
+
const isExpired = creds.expiresAt <= now;
|
|
199
|
+
const expiresIn = creds.expiresAt - now;
|
|
200
|
+
if (isExpired) {
|
|
201
|
+
return `⚠️ Authentication expired for ${creds.email || 'unknown user'}. Use "login to Acuity" to re-authenticate.`;
|
|
202
|
+
}
|
|
203
|
+
const minutes = Math.floor(expiresIn / 60);
|
|
204
|
+
const refreshStatus = creds.refreshToken ? '✅ Auto-refresh enabled' : '⚠️ No refresh token';
|
|
205
|
+
const env = getEnvironment();
|
|
206
|
+
return `✅ **Authenticated**
|
|
207
|
+
|
|
208
|
+
Environment: ${env.name}
|
|
209
|
+
User: ${creds.email || 'unknown user'}
|
|
210
|
+
Token expires in: ${minutes} minutes
|
|
211
|
+
${refreshStatus}`;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=init-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-auth.js","sourceRoot":"","sources":["../../src/tools/init-auth.ts"],"names":[],"mappings":"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"}
|