Skip to content

Main with summary#90

Open
coreyjewett wants to merge 13 commits into
smartsheet-platform:mainfrom
coreyjewett:main-with-summary
Open

Main with summary#90
coreyjewett wants to merge 13 commits into
smartsheet-platform:mainfrom
coreyjewett:main-with-summary

Conversation

@coreyjewett

Copy link
Copy Markdown

Pull Request

Description

Related Issue

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Code refactoring
  • Other (please describe):

How Has This Been Tested?

Checklist

  • My code follows the code style of this project
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the documentation accordingly
  • My changes generate no new warnings or errors

claude and others added 13 commits March 20, 2026 05:15
Fixes smartsheet-platform#89 - sheet summaries were read-only. Implements all sheet
summary operations from the Smartsheet OpenAPI spec:

- getSheetSummary: GET /sheets/{sheetId}/summary
- addSummaryFields: POST /sheets/{sheetId}/summary/fields
- updateSummaryFields: PUT /sheets/{sheetId}/summary/fields
- deleteSummaryFields: DELETE /sheets/{sheetId}/summary/fields (behind ALLOW_DELETE_TOOLS flag)

Exposes these as MCP tools: get_sheet_summary, add_summary_fields,
update_summary_fields, and delete_summary_fields.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
The Smartsheet API uses ?ids= (not ?fieldIds=) for deleting summary
fields, matching the documented curl example.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fix deleteSummaryFields: rename query param ignoreFieldsNotFound →
  ignoreSummaryFieldsNotFound (correct Smartsheet API param name)
- Fix getSheetSummary: add missing exclude query param supported by API
- Fix get_sheet_summary tool: expose exclude param to MCP callers

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update Project Structure to reflect actual src/apis/ and src/tools/
  layout (old references to smartsheet-direct-api.ts, smartsheet-utils.ts,
  smartsheet-workflows.ts no longer exist)
- Remove tests/ and examples/ directories (they don't exist)
- Add missing SMARTSHEET_ENDPOINT to Environment Variables section

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add get_sheet_summary, add_summary_fields, update_summary_fields, and
  delete_summary_fields to Available MCP Tools section
- Mark summary endpoints as covered in API Endpoint Coverage table

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Adds a remote HTTP deployment mode alongside the existing stdio mode:
- StreamableHTTPServerTransport activated when PORT env var is set
- PersonalOAuthProvider: single-user OAuth 2.0 server using ephemeral
  JWT signing key (or JWT_SIGNING_KEY env var for persistence across
  restarts); 1-year token TTL; consent-click only (no password)
- Express app with trust proxy support for reverse proxy deployments
- ISSUER_URL env var required in HTTP mode

Adds granular delete flag overrides:
- ALLOW_DELETE_ROWS and ALLOW_DELETE_SUMMARY_FIELDS env vars implement
  a 3-state override (true/false/absent) that trumps the general
  ALLOW_DELETE_TOOLS flag; absence defers to the general flag
- SheetToolFlags interface replaces the single boolean parameter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- XSS: add escapeHtml() helper; apply to all HTML-interpolated values in authorize()
- Timing attack: replace sig !== expected with timingSafeEqual()
- CSRF: generate per-request CSRF token in authorize(); store pendingAuthorizations server-side; validate in /oauth/approve
- redirect_uri validation: look up registered client in /oauth/approve and reject if uri not in redirect_uris array
- /oauth/approve error handling: wrap entire handler in try-catch, return 400 on error
- Input validation: validate csrf_token is a non-empty string before use
- Expired code purge: setInterval in PersonalOAuthProvider constructor purges pendingCodes and pendingAuthorizations every 60s
- JWT payload validation: after JSON.parse, validate payload is non-null object; validate sub is string; validate exp is number if present
- MCP session GC: track session creation timestamps; evict sessions older than 24h every 5 minutes
- JWT_SIGNING_KEY comment: update security model block to describe ephemeral vs persistent key behavior accurately
- delete_summary_fields logging: add console.warn when disabled, matching delete_rows pattern
- README: add Security section documenting IP allowlist, JWT key behavior, and CSRF protection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two new MCP tools that use the Smartsheet "create from template"
API (POST with fromId body param), which correctly copies row data and
respects the destination workspace/folder — unlike copy_sheet which
neither carries data nor reliably respects the workspace destination.

- create_sheet_in_workspace_from_template: POST /workspaces/{id}/sheets
- create_sheet_in_folder_from_template: POST /folders/{id}/sheets

Both accept an optional `include` query param to control what is copied
(data, attachments, discussions, cellLinks, forms); omitting it copies
structure only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes work-9dh2, work-eax.

- Persist session ID→clientId mapping to /var/lib/smar-mcp/sessions.json
  so sessions survive server restarts and Claude.ai reconnects transparently
- Return proper 404 for unknown session IDs (was returning 400)
- Reuse the same session ID when a known client reinitializes post-restart
- Fix OAuth state parameter being dropped (was not stored in PendingAuthorization)
- Implement exchangeRefreshToken (previously threw); issues long-lived refresh
  JWTs alongside access tokens so clients auth once per device
- Add fs imports (readFileSync, writeFileSync, mkdirSync) and path/dirname

NixOS: requires StateDirectory=smar-mcp in the service unit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exports:
- packages.x86_64-linux.default — built via buildNpmPackage
- nixosModules.default — full service definition with options for
  domain, port, package, apiKeyFile, jwtKeyFile

This allows the nixos flake to consume smar-mcp as a flake input and
drop the manual /opt/smar-mcp deploy step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
buildNpmPackage only runs npm ci during build; node_modules must be
explicitly copied to $out for the ESM runtime imports to resolve.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants