Skip to content

Commit 13491e5

Browse files
committed
Fix TypeScript compilation errors in MCP server
- Resolve type conversion errors in graph-service.ts - Make interface properties optional to handle MCP dynamic arguments - Fix Neo4jValue property access with proper type casting - Add missing type property to UpdateNodeArgs interface
1 parent 29fd069 commit 13491e5

2 files changed

Lines changed: 109 additions & 78 deletions

File tree

packages/mcp-server/src/services/graph-service.ts

Lines changed: 97 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import {
1919
AnalysisResults,
2020
WorkloadData,
2121
CapacityAnalysis,
22-
WorkloadPredictions
22+
WorkloadPredictions,
23+
GetContributorPrioritiesArgs,
24+
GetContributorWorkloadArgs
2325
} from '../types/graph.js';
2426
import {
2527
sanitizeString,
@@ -113,15 +115,15 @@ export interface DetectCyclesArgs {
113115
}
114116

115117
export interface UpdatePrioritiesArgs {
116-
node_id: string;
118+
node_id?: string;
117119
priority_executive?: number;
118120
priority_individual?: number;
119121
priority_community?: number;
120122
recalculate_computed?: boolean;
121123
}
122124

123125
export interface BulkUpdatePrioritiesArgs {
124-
updates: Array<{
126+
updates?: Array<{
125127
node_id: string;
126128
priority_executive?: number;
127129
priority_individual?: number;
@@ -154,7 +156,7 @@ export interface GetBottlenecksArgs {
154156
}
155157

156158
export interface BulkOperationsArgs {
157-
operations: Array<{
159+
operations?: Array<{
158160
type: 'create_node' | 'update_node' | 'create_edge' | 'delete_edge';
159161
params: CreateNodeArgs | UpdateNodeArgs | CreateEdgeArgs | DeleteEdgeArgs;
160162
}>;
@@ -170,7 +172,7 @@ export interface GetWorkloadAnalysisArgs {
170172
}
171173

172174
export interface CreateGraphArgs {
173-
name: string;
175+
name?: string;
174176
description?: string;
175177
type?: GraphType;
176178
status?: GraphStatus;
@@ -181,7 +183,7 @@ export interface CreateGraphArgs {
181183
}
182184

183185
export interface UpdateGraphArgs {
184-
graphId: string;
186+
graphId?: string;
185187
name?: string;
186188
description?: string;
187189
status?: GraphStatus;
@@ -190,22 +192,22 @@ export interface UpdateGraphArgs {
190192
}
191193

192194
export interface DeleteGraphArgs {
193-
graphId: string;
195+
graphId?: string;
194196
force?: boolean;
195197
}
196198

197199
export interface GetGraphDetailsArgs {
198-
graphId: string;
200+
graphId?: string;
199201
}
200202

201203
export interface ArchiveGraphArgs {
202-
graphId: string;
204+
graphId?: string;
203205
reason?: string;
204206
}
205207

206208
export interface CloneGraphArgs {
207-
sourceGraphId: string;
208-
newName: string;
209+
sourceGraphId?: string;
210+
newName?: string;
209211
includeNodes?: boolean;
210212
includeEdges?: boolean;
211213
teamId?: string;
@@ -1555,7 +1557,7 @@ export class GraphService {
15551557
obj[keyStr] = typeof value?.toNumber === 'function' ? value.toNumber() : value;
15561558
});
15571559
return obj;
1558-
});
1560+
}) as unknown as Neo4jValue;
15591561
}
15601562
} catch (error) {
15611563
results[name] = { error: error instanceof Error ? error.message : String(error) };
@@ -1722,7 +1724,7 @@ export class GraphService {
17221724
status: record.get('status'),
17231725
priority: record.get('priority'),
17241726
dependent_count: record.get('dependent_count').toNumber()
1725-
}));
1727+
})) as unknown as Neo4jValue;
17261728
} catch (error) {
17271729
results.potential_bottlenecks = { error: error instanceof Error ? error.message : String(error) };
17281730
}
@@ -1732,16 +1734,16 @@ export class GraphService {
17321734
let healthScore = 1.0;
17331735
const healthFactors = [];
17341736

1735-
if (results.priority_balance && !results.priority_balance.error) {
1736-
const stdDev = results.priority_balance.distribution.standard_deviation;
1737+
if (results.priority_balance && !(results.priority_balance as any).error) {
1738+
const stdDev = (results.priority_balance as any).distribution.standard_deviation;
17371739
if (stdDev > 0.3) {
17381740
healthScore -= 0.1;
17391741
healthFactors.push("High priority variance detected");
17401742
}
17411743
}
17421744

1743-
if (results.dependency_health && !results.dependency_health.error) {
1744-
const depRatio = results.dependency_health.dependency_ratio;
1745+
if (results.dependency_health && !(results.dependency_health as any).error) {
1746+
const depRatio = (results.dependency_health as any).dependency_ratio;
17451747
if (depRatio > 0.2) {
17461748
healthScore -= 0.15;
17471749
healthFactors.push("Too many heavily dependent nodes");
@@ -1779,8 +1781,8 @@ export class GraphService {
17791781
private generateHealthRecommendations(results: AnalysisResults): string[] {
17801782
const recommendations = [];
17811783

1782-
if (results.priority_balance && !results.priority_balance.error) {
1783-
const { distribution } = results.priority_balance;
1784+
if (results.priority_balance && !(results.priority_balance as any).error) {
1785+
const { distribution } = results.priority_balance as any;
17841786
if (distribution.high_priority_ratio > 0.3) {
17851787
recommendations.push("Consider reviewing high-priority items - too many items marked as high priority may indicate poor prioritization");
17861788
}
@@ -1789,8 +1791,8 @@ export class GraphService {
17891791
}
17901792
}
17911793

1792-
if (results.dependency_health && !results.dependency_health.error) {
1793-
const { avg_dependencies_per_node, dependency_ratio } = results.dependency_health;
1794+
if (results.dependency_health && !(results.dependency_health as any).error) {
1795+
const { avg_dependencies_per_node, dependency_ratio } = results.dependency_health as any;
17941796
if (avg_dependencies_per_node > 3) {
17951797
recommendations.push("High average dependencies per node - consider simplifying dependencies to reduce complexity");
17961798
}
@@ -1877,7 +1879,7 @@ export class GraphService {
18771879
record.get('status'),
18781880
record.get('priority')
18791881
)
1880-
}));
1882+
})) as unknown as Neo4jValue;
18811883
} catch (error) {
18821884
results.high_dependency_bottlenecks = { error: error instanceof Error ? error.message : String(error) };
18831885
}
@@ -1889,7 +1891,7 @@ export class GraphService {
18891891
blocked_title: record.get('blocked_title'),
18901892
blocking_items: record.get('blocking_items'),
18911893
chain_length: record.get('blocking_items').length
1892-
}));
1894+
})) as unknown as Neo4jValue;
18931895
} catch (error) {
18941896
results.blocked_chains = { error: error instanceof Error ? error.message : String(error) };
18951897
}
@@ -1950,7 +1952,7 @@ export class GraphService {
19501952
const resolutions = [];
19511953

19521954
if (Array.isArray(results.high_dependency_bottlenecks)) {
1953-
for (const bottleneck of results.high_dependency_bottlenecks) {
1955+
for (const bottleneck of results.high_dependency_bottlenecks as any[]) {
19541956
if (bottleneck.bottleneck_severity === 'critical' || bottleneck.bottleneck_severity === 'high') {
19551957
if (bottleneck.status === 'PROPOSED') {
19561958
resolutions.push({
@@ -1970,7 +1972,7 @@ export class GraphService {
19701972
}
19711973

19721974
if (Array.isArray(results.blocked_chains)) {
1973-
for (const chain of results.blocked_chains) {
1975+
for (const chain of results.blocked_chains as any[]) {
19741976
if (chain.chain_length > 1) {
19751977
resolutions.push({
19761978
type: 'break_dependency_chain',
@@ -2005,8 +2007,8 @@ export class GraphService {
20052007
// Check for ID collisions in create operations
20062008
const createNodeIds: string[] = [];
20072009
operations.forEach(op => {
2008-
if (op.type === 'create_node' && op.params?.id) {
2009-
createNodeIds.push(op.params.id);
2010+
if (op.type === 'create_node' && (op.params as any)?.id) {
2011+
createNodeIds.push((op.params as any).id);
20102012
}
20112013
});
20122014

@@ -2037,7 +2039,7 @@ export class GraphService {
20372039
try {
20382040
for (const operation of operations) {
20392041
try {
2040-
const result = await this.executeBulkOperation(tx, operation);
2042+
const result = await this.executeBulkOperation(tx, operation as { type: string; params: Record<string, Neo4jValue> });
20412043
results.push({
20422044
operation_type: operation.type,
20432045
success: true,
@@ -2088,7 +2090,7 @@ export class GraphService {
20882090
// Execute operations individually
20892091
for (const operation of operations) {
20902092
try {
2091-
const result = await this.executeBulkOperation(session, operation);
2093+
const result = await this.executeBulkOperation(session, operation as { type: string; params: Record<string, Neo4jValue> });
20922094
results.push({
20932095
operation_type: operation.type,
20942096
success: true,
@@ -2122,7 +2124,7 @@ export class GraphService {
21222124
});
21232125
}
21242126

2125-
private async executeBulkOperation(sessionOrTx: Session, operation: { type: string; params: Record<string, Neo4jValue> }) {
2127+
private async executeBulkOperation(sessionOrTx: Session | any, operation: { type: string; params: Record<string, Neo4jValue> }) {
21262128
const { type, params } = operation;
21272129

21282130
switch (type) {
@@ -2349,20 +2351,21 @@ export class GraphService {
23492351
results.contributor_workloads = Array.from(workloadMap.values());
23502352

23512353
// Calculate summary statistics
2352-
const totalItems = results.contributor_workloads.reduce((sum: number, c: Record<string, Neo4jValue>) => sum + (c.total_items as number), 0);
2353-
const avgItemsPerContributor = results.contributor_workloads.length > 0
2354-
? totalItems / results.contributor_workloads.length
2354+
const totalItems = (results.contributor_workloads as unknown as Record<string, Neo4jValue>[]).reduce((sum: number, c: Record<string, Neo4jValue>) => sum + (c.total_items as number), 0);
2355+
const workloadsArray = results.contributor_workloads as unknown as Record<string, Neo4jValue>[];
2356+
const avgItemsPerContributor = workloadsArray.length > 0
2357+
? totalItems / workloadsArray.length
23552358
: 0;
23562359

23572360
results.summary = {
2358-
total_contributors: results.contributor_workloads.length,
2361+
total_contributors: workloadsArray.length,
23592362
total_items: totalItems,
23602363
avg_items_per_contributor: avgItemsPerContributor,
2361-
most_loaded_contributor: results.contributor_workloads[0]?.contributor_id,
2364+
most_loaded_contributor: (workloadsArray[0] as any)?.contributor_id,
23622365
workload_distribution: {
2363-
heavily_loaded: results.contributor_workloads.filter((c: Record<string, Neo4jValue>) => (c.total_items as number) > avgItemsPerContributor * 1.5).length,
2364-
moderately_loaded: results.contributor_workloads.filter((c: Record<string, Neo4jValue>) => (c.total_items as number) >= avgItemsPerContributor * 0.5 && (c.total_items as number) <= avgItemsPerContributor * 1.5).length,
2365-
lightly_loaded: results.contributor_workloads.filter((c: Record<string, Neo4jValue>) => (c.total_items as number) < avgItemsPerContributor * 0.5).length
2366+
heavily_loaded: workloadsArray.filter((c: Record<string, Neo4jValue>) => (c.total_items as number) > avgItemsPerContributor * 1.5).length,
2367+
moderately_loaded: workloadsArray.filter((c: Record<string, Neo4jValue>) => (c.total_items as number) >= avgItemsPerContributor * 0.5 && (c.total_items as number) <= avgItemsPerContributor * 1.5).length,
2368+
lightly_loaded: workloadsArray.filter((c: Record<string, Neo4jValue>) => (c.total_items as number) < avgItemsPerContributor * 0.5).length
23662369
}
23672370
};
23682371

@@ -2372,12 +2375,12 @@ export class GraphService {
23722375

23732376
// Add capacity analysis if requested
23742377
if (include_capacity && !results.error) {
2375-
results.capacity_analysis = this.generateCapacityAnalysis(results.contributor_workloads);
2378+
results.capacity_analysis = this.generateCapacityAnalysis(results.contributor_workloads as unknown as WorkloadData[]) as unknown as Neo4jValue;
23762379
}
23772380

23782381
// Add predictions if requested
23792382
if (include_predictions && !results.error) {
2380-
results.predictions = this.generateWorkloadPredictions(results.contributor_workloads);
2383+
results.predictions = this.generateWorkloadPredictions(results.contributor_workloads as unknown as WorkloadData[]) as unknown as Neo4jValue;
23812384
}
23822385

23832386
return {
@@ -2479,13 +2482,17 @@ export class GraphService {
24792482
}
24802483

24812484
// Contributor-Focused Methods
2482-
async getContributorPriorities(args: {
2483-
contributor_id: string;
2484-
limit?: number;
2485-
priority_type?: 'all' | 'executive' | 'individual' | 'community' | 'composite';
2486-
status_filter?: string[];
2487-
include_dependencies?: boolean;
2488-
}) {
2485+
async getContributorPriorities(args: GetContributorPrioritiesArgs) {
2486+
if (!args.contributor_id) {
2487+
return {
2488+
content: [{
2489+
type: 'text',
2490+
text: JSON.stringify({ error: 'contributor_id is required' })
2491+
}],
2492+
isError: true
2493+
};
2494+
}
2495+
24892496
const limit = args.limit || 10;
24902497
const priorityType = args.priority_type || 'composite';
24912498
const statusFilter = args.status_filter || ['PROPOSED', 'PLANNED', 'ACTIVE', 'IN_PROGRESS', 'BLOCKED'];
@@ -2551,14 +2558,17 @@ export class GraphService {
25512558
}
25522559
}
25532560

2554-
async getContributorWorkload(args: {
2555-
contributor_id: string;
2556-
include_projects?: boolean;
2557-
include_priority_distribution?: boolean;
2558-
include_type_distribution?: boolean;
2559-
include_timeline?: boolean;
2560-
time_window_days?: number;
2561-
}) {
2561+
async getContributorWorkload(args: GetContributorWorkloadArgs) {
2562+
if (!args.contributor_id) {
2563+
return {
2564+
content: [{
2565+
type: 'text',
2566+
text: JSON.stringify({ error: 'contributor_id is required' })
2567+
}],
2568+
isError: true
2569+
};
2570+
}
2571+
25622572
const session = this.driver.session();
25632573
try {
25642574
// Get basic workload stats
@@ -2709,12 +2719,22 @@ export class GraphService {
27092719
}
27102720

27112721
async getProjectTeam(args: {
2712-
graph_id: string;
2722+
graph_id?: string;
27132723
include_roles?: boolean;
27142724
include_collaboration?: boolean;
27152725
include_capacity?: boolean;
27162726
depth?: number;
27172727
}) {
2728+
if (!args.graph_id) {
2729+
return {
2730+
content: [{
2731+
type: 'text',
2732+
text: JSON.stringify({ error: 'graph_id is required' })
2733+
}],
2734+
isError: true
2735+
};
2736+
}
2737+
27182738
const session = this.driver.session();
27192739
try {
27202740
const query = `
@@ -2770,13 +2790,23 @@ export class GraphService {
27702790
}
27712791

27722792
async getContributorExpertise(args: {
2773-
contributor_id: string;
2793+
contributor_id?: string;
27742794
include_work_types?: boolean;
27752795
include_projects?: boolean;
27762796
include_success_patterns?: boolean;
27772797
time_window_days?: number;
27782798
min_items_threshold?: number;
27792799
}) {
2800+
if (!args.contributor_id) {
2801+
return {
2802+
content: [{
2803+
type: 'text',
2804+
text: JSON.stringify({ error: 'contributor_id is required' })
2805+
}],
2806+
isError: true
2807+
};
2808+
}
2809+
27802810
const session = this.driver.session();
27812811
try {
27822812
const timeWindow = args.time_window_days || 90;
@@ -2815,22 +2845,23 @@ export class GraphService {
28152845

28162846
if (args.include_work_types) {
28172847
itemDetails.forEach((item: Record<string, Neo4jValue>) => {
2818-
if (!workTypeExpertise[item.type]) {
2819-
workTypeExpertise[item.type] = { count: 0, completed: 0, avgPriority: 0 };
2848+
const itemType = String(item.type);
2849+
if (!workTypeExpertise[itemType]) {
2850+
workTypeExpertise[itemType] = { count: 0, completed: 0, avgPriority: 0 };
28202851
}
2821-
workTypeExpertise[item.type].count++;
2852+
workTypeExpertise[itemType].count = (workTypeExpertise[itemType].count as number) + 1;
28222853
if (item.status === 'COMPLETED') {
2823-
workTypeExpertise[item.type].completed++;
2854+
workTypeExpertise[itemType].completed = (workTypeExpertise[itemType].completed as number) + 1;
28242855
}
2825-
workTypeExpertise[item.type].avgPriority += item.priority;
2856+
workTypeExpertise[itemType].avgPriority = (workTypeExpertise[itemType].avgPriority as number) + (item.priority as number);
28262857
});
28272858

28282859
Object.keys(workTypeExpertise).forEach(type => {
28292860
const expertise = workTypeExpertise[type];
2830-
expertise.avgPriority = expertise.avgPriority / expertise.count;
2831-
expertise.completionRate = expertise.completed / expertise.count;
2832-
expertise.expertiseLevel = expertise.count >= minThreshold ?
2833-
(expertise.completionRate > 0.8 ? 'Expert' : 'Proficient') : 'Beginner';
2861+
expertise.avgPriority = (expertise.avgPriority as number) / (expertise.count as number);
2862+
expertise.completionRate = (expertise.completed as number) / (expertise.count as number);
2863+
expertise.expertiseLevel = (expertise.count as number) >= minThreshold ?
2864+
((expertise.completionRate as number) > 0.8 ? 'Expert' : 'Proficient') : 'Beginner';
28342865
});
28352866
}
28362867

0 commit comments

Comments
 (0)