Skip to main content
Glama

Targetprocess MCP Server

# Contributing to Targetprocess MCP Server Welcome to the Targetprocess MCP Server project! 🎯 This project goes beyond simple API wrappers - we're building intelligent, context-aware workflows that understand how people actually work. Your contributions should enhance this intelligence, not just add features. ## Table of Contents - [Getting Started](#getting-started) - [Architecture Overview](#architecture-overview) - [Contribution Guidelines](#contribution-guidelines) - [Code Style and Standards](#code-style-and-standards) - [Pull Request Process](#pull-request-process) - [Testing Requirements](#testing-requirements) - [Examples](#examples) ## Getting Started ### Development Environment Setup 1. **Clone the repository** ```bash git clone https://github.com/aaronsb/apptio-target-process-mcp.git cd apptio-target-process-mcp ``` 2. **Install dependencies** ```bash npm install ``` 3. **Set up your environment** ```bash # Copy the example config cp .env.example .env # Edit with your Targetprocess credentials # IMPORTANT: Set TP_USER_ROLE to test different personas ``` 4. **Build and test** ```bash npm run build npm run test npm run lint ``` 5. **Run the MCP inspector** (for interactive testing) ```bash npm run inspector ``` 6. **Initialize documentation search** (optional but recommended) ```bash pushd resources/target-process-docs && npm install && ./refresh-docs.sh && popd ``` ## Architecture Overview Before contributing, please read our [Architecture Documentation](docs/ARCHITECTURE.md) to understand: - The three-layer architecture (Entities, API, Tools) - **Semantic Operations Philosophy** - Our core approach to building intelligent workflows - Role-based operation filtering - Dynamic discovery patterns ### Understanding Semantic Operations is Critical This project's core innovation is **semantic operations** - intelligent, context-aware workflows that understand how people actually work. Before writing any code: 1. **Read the [Semantic Operations Documentation](docs/semantic-operations/README.md)** to understand the philosophy and patterns 2. **Review role-specific examples** in the semantic operations directory 3. **Understand the difference** between raw tools (simple API wrappers) and semantic operations (intelligent workflows) **Key principle**: We build tools that understand context and adapt to how users work, not just expose API endpoints. Semantic operations are how we achieve this. ## Contribution Guidelines ### 1. Understand Semantic Operations First Before writing any code, ask yourself: - **Is this a workflow that benefits from intelligence?** → Create a semantic operation - **Is this a low-level utility?** → Create a raw tool - **Does this vary by user role?** → Make it role-aware ### 2. When to Create Semantic Operations vs Raw Tools **Create a Semantic Operation when:** - The task involves multiple steps or decisions - Different roles would approach it differently - Context from previous actions matters - You need to discover capabilities dynamically - The operation benefits from intelligent error recovery **Create a Raw Tool when:** - It's a simple, atomic operation - The behavior is identical for all users - It's a utility function (like `inspect_object`) - It provides foundational capabilities for semantic operations ### 3. Role-Based Filtering is Essential Our users have different needs: - **Developers**: Focus on tasks, bugs, and time tracking - **Project Managers**: Focus on planning, reporting, and team coordination - **Testers**: Focus on test cases, bug verification, and quality metrics Your contribution should respect these differences: ```typescript // Good: Role-aware operation if (this.context.userRole === 'developer') { return this.getDeveloperFocusedView(); } // Bad: One-size-fits-all return this.getAllData(); // Overwhelming and not helpful ``` ### 4. Dynamic Discovery Over Hard-Coded Assumptions Never assume: - Entity state names (discover them!) - Field availability (check first!) - Workflow transitions (query the API!) ```typescript // Good: Dynamic discovery const states = await this.discoverEntityStates('Task'); const inProgressState = states.find(s => s.name.toLowerCase().includes('progress') ); // Bad: Hard-coded assumption const inProgressStateId = 45; // Will break in other environments! ``` ### 5. Context is King Every operation should consider: - What the user is trying to achieve (intent) - What they've done before (history) - What they'll likely do next (workflow) - How to help when things go wrong (recovery) ## Code Style and Standards ### Semantic Operation Patterns Follow the established pattern for semantic operations: ```typescript export class MyWorkflowOperation extends SemanticOperation<MyParams> { async execute(params: MyParams): Promise<MyResult> { try { // 1. Validate and understand intent const context = await this.buildContext(params); // 2. Discover capabilities dynamically const capabilities = await this.discoverCapabilities(); // 3. Execute with intelligence const result = await this.performOperation(context, capabilities); // 4. Provide helpful context in response return this.formatResultWithContext(result); } catch (error) { // 5. Intelligent error handling return this.handleErrorWithGuidance(error); } } } ``` ### Error Handling with Context Errors should guide users, not just report failures: ```typescript // Good: Contextual error handling catch (error) { if (error.code === 'STATE_TRANSITION_INVALID') { const validTransitions = await this.getValidTransitions(); throw new McpError( 'INVALID_REQUEST', `Cannot transition to that state. Valid transitions: ${validTransitions.join(', ')}. ` + `Try 'In Progress' first.` ); } } // Bad: Generic error catch (error) { throw new Error('Operation failed'); } ``` ### Type Safety and Validation - Use TypeScript's type system fully - Validate with Zod schemas at boundaries - Prefer `unknown` over `any` - Model domain concepts as types ## Pull Request Process ### Before Submitting 1. **Run all checks locally** ```bash npm run lint npm run test npm run build ``` 2. **Test with different roles** ```bash TP_USER_ROLE=developer npm run inspector TP_USER_ROLE=project-manager npm run inspector ``` 3. **Update documentation** if you've added new operations or changed behavior ### PR Checklist Your PR description should address: - [ ] **Have you read the [Semantic Operations Documentation](docs/semantic-operations/README.md)?** - This is required reading before any contribution - Understand the philosophy before writing code - [ ] **Have you considered if this should be a semantic operation?** - If it's a workflow, it probably should be - If it adapts to context, it definitely should be - Refer to the semantic operations docs for guidance - [ ] **Is this operation role-aware if appropriate?** - Does it filter/adapt based on user role? - Have you tested with different roles? - [ ] **Does this follow dynamic discovery patterns?** - No hard-coded IDs or state names - Discovers capabilities at runtime - Handles discovery failures gracefully - [ ] **Does error handling provide actionable guidance?** - Users know what went wrong - Users know how to fix it - Fallback options are provided - [ ] **Have you added appropriate tests?** - Unit tests for logic - Integration tests for workflows - Role-based behavior tests - [ ] **Is the code self-documenting?** - Clear intent in naming - Comments explain "why" not "what" - Complex logic is extracted and named ### PR Title Format Use conventional commits: - `feat(semantic): add smart task prioritization` - `fix(discovery): handle missing entity states` - `docs: update semantic operation examples` - `refactor(roles): extract role detection logic` ## Testing Requirements ### Testing Semantic Operations 1. **Test the happy path** - Normal workflow execution 2. **Test role variations** - Different behavior per role 3. **Test discovery failures** - When API doesn't provide expected data 4. **Test error scenarios** - With helpful recovery paths Example test structure: ```typescript describe('StartWorkingOn', () => { it('should discover and use correct in-progress state', async () => { // Mock dynamic discovery mockDiscoverStates.mockResolvedValue([ { id: 1, name: 'Open' }, { id: 2, name: 'In Progress' } ]); const result = await operation.execute({ taskId: 123 }); expect(mockUpdateEntity).toHaveBeenCalledWith( expect.objectContaining({ entityState: { id: 2 } // Discovered, not hard-coded! }) ); }); it('should handle missing in-progress state gracefully', async () => { mockDiscoverStates.mockResolvedValue([ { id: 1, name: 'Open' }, { id: 3, name: 'Done' } ]); const result = await operation.execute({ taskId: 123 }); expect(result.message).toContain('manual state update may be needed'); }); }); ``` ### Testing with Different Roles ```typescript describe.each(['developer', 'project-manager', 'tester'])('as %s', (role) => { beforeEach(() => { context.userRole = role; }); it('should provide role-appropriate operations', async () => { const operations = await getAvailableOperations(context); if (role === 'developer') { expect(operations).toContain('start_working_on'); expect(operations).not.toContain('approve_release'); } // ... role-specific assertions }); }); ``` ## Examples ### Good Contribution: Smart Comment System ```typescript // Semantic operation that understands context export class AddCommentOperation extends SemanticOperation<AddCommentParams> { async execute(params: AddCommentParams): Promise<Result> { // Discovers entity type and current state const entity = await this.getEntity(params.entityId); // Adds contextual information const enrichedComment = this.enrichComment(params.comment, { mentionSuggestions: await this.suggestMentions(entity), statusContext: this.getStatusContext(entity), relatedItems: await this.findRelatedItems(entity) }); // Handles based on entity type and state const result = await this.postComment(enrichedComment); // Suggests next actions return { ...result, suggestions: this.getNextActionSuggestions(entity, result) }; } } ``` ### Problematic Contribution: Hard-Coded State Updater ```typescript // Raw API wrapper with hard-coded assumptions export function updateTaskStatus(taskId: number, status: string) { // Hard-coded state IDs - will break! const stateMap = { 'open': 123, 'in-progress': 456, 'done': 789 }; // No role awareness // No error guidance // No context understanding return api.update(`/Task/${taskId}`, { EntityState: { Id: stateMap[status] } }); } ``` ### Good Test Example ```typescript it('should adapt search behavior to user role', async () => { const developer = new SearchContext({ role: 'developer' }); const manager = new SearchContext({ role: 'project-manager' }); const devResults = await search.execute({ query: 'urgent' }, developer); const mgrResults = await search.execute({ query: 'urgent' }, manager); // Developer sees their assigned urgent tasks expect(devResults.every(r => r.assignedTo === developer.userId)).toBe(true); // Manager sees team-wide urgent items expect(mgrResults.some(r => r.assignedTo !== manager.userId)).toBe(true); }); ``` ## Questions or Need Help? - Check existing issues and PRs for similar work - Read the architecture documentation thoroughly - Ask questions in PR discussions - we're here to help! - When in doubt, prototype as a semantic operation Remember: We're building tools that understand how people work, not just what APIs can do. Your contribution should make someone's workday a little bit easier and a lot more intelligent. Thank you for contributing to making project management more intelligent! 🚀

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aaronsb/apptio-target-process-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server