#
tokens: 12183/50000 15/16 files (page 1/2)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 of 2. Use http://codebase.md/spathodea-network/opencti-mcp?page={x} to view the full context.

# Directory Structure

```
├── .env.example
├── .gitignore
├── Dockerfile
├── LICENSE
├── package.json
├── README.md
├── README.zh-TW.md
├── smithery.yaml
├── src
│   ├── index.ts
│   ├── opencti.graphql
│   └── queries
│       ├── metadata.ts
│       ├── references.ts
│       ├── relationships.ts
│       ├── reports.ts
│       ├── stix_objects.ts
│       ├── system.ts
│       └── users.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
# OpenCTI Configuration
OPENCTI_URL=http://localhost:8080
OPENCTI_TOKEN=your-api-token-here

```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependencies
node_modules/
package-lock.json

# Build output
build/
dist/

# Environment files
.env
.env.local
.env.*.local

# IDE files
.vscode/
.idea/
*.iml

# Logs
logs/
*.log
npm-debug.log*

# System files
.DS_Store
Thumbs.db

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# OpenCTI MCP Server

[![smithery badge](https://smithery.ai/badge/opencti-server)](https://smithery.ai/server/opencti-server)
[Traditional Chinese (繁體中文)](README.zh-TW.md)

<a href="https://glama.ai/mcp/servers/ml61kiz1gm"><img width="380" height="200" src="https://glama.ai/mcp/servers/ml61kiz1gm/badge" alt="OpenCTI Server MCP server" /></a>

## Overview
OpenCTI MCP Server is a Model Context Protocol (MCP) server that provides seamless integration with OpenCTI (Open Cyber Threat Intelligence) platform. It enables querying and retrieving threat intelligence data through a standardized interface.

## Features
- Fetch and search threat intelligence data
  - Get latest reports and search by ID
  - Search for malware information
  - Query indicators of compromise
  - Search for threat actors
- User and group management
  - List all users and groups
  - Get user details by ID
- STIX object operations
  - List attack patterns
  - Get campaign information by name
- System management
  - List connectors
  - View status templates
- File operations
  - List all files
  - Get file details by ID
- Reference data access
  - List marking definitions
  - View available labels
- Customizable query limits
- Full GraphQL query support

## Prerequisites
- Node.js 16 or higher
- Access to an OpenCTI instance
- OpenCTI API token

## Installation

### Installing via Smithery

To install OpenCTI Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/opencti-server):

```bash
npx -y @smithery/cli install opencti-server --client claude
```

### Manual Installation
```bash
# Clone the repository
git clone https://github.com/yourusername/opencti-mcp-server.git

# Install dependencies
cd opencti-mcp-server
npm install

# Build the project
npm run build
```

## Configuration

### Environment Variables
Copy `.env.example` to `.env` and update with your OpenCTI credentials:
```bash
cp .env.example .env
```

Required environment variables:
- `OPENCTI_URL`: Your OpenCTI instance URL
- `OPENCTI_TOKEN`: Your OpenCTI API token

### MCP Settings
Create a configuration file in your MCP settings location:
```json
{
  "mcpServers": {
    "opencti": {
      "command": "node",
      "args": ["path/to/opencti-server/build/index.js"],
      "env": {
        "OPENCTI_URL": "${OPENCTI_URL}",  // Will be loaded from .env
        "OPENCTI_TOKEN": "${OPENCTI_TOKEN}"  // Will be loaded from .env
      }
    }
  }
}
```

### Security Notes
- Never commit `.env` file or API tokens to version control
- Keep your OpenCTI credentials secure
- The `.gitignore` file is configured to exclude sensitive files

## Available Tools

## Available Tools

### Reports
#### get_latest_reports
Retrieves the most recent threat intelligence reports.
```typescript
{
  "name": "get_latest_reports",
  "arguments": {
    "first": 10  // Optional, defaults to 10
  }
}
```

#### get_report_by_id
Retrieves a specific report by its ID.
```typescript
{
  "name": "get_report_by_id",
  "arguments": {
    "id": "report-uuid"  // Required
  }
}
```

### Search Operations
#### search_malware
Searches for malware information in the OpenCTI database.
```typescript
{
  "name": "search_malware",
  "arguments": {
    "query": "ransomware",
    "first": 10  // Optional, defaults to 10
  }
}
```

#### search_indicators
Searches for indicators of compromise.
```typescript
{
  "name": "search_indicators",
  "arguments": {
    "query": "domain",
    "first": 10  // Optional, defaults to 10
  }
}
```

#### search_threat_actors
Searches for threat actor information.
```typescript
{
  "name": "search_threat_actors",
  "arguments": {
    "query": "APT",
    "first": 10  // Optional, defaults to 10
  }
}
```

### User Management
#### get_user_by_id
Retrieves user information by ID.
```typescript
{
  "name": "get_user_by_id",
  "arguments": {
    "id": "user-uuid"  // Required
  }
}
```

#### list_users
Lists all users in the system.
```typescript
{
  "name": "list_users",
  "arguments": {}
}
```

#### list_groups
Lists all groups with their members.
```typescript
{
  "name": "list_groups",
  "arguments": {
    "first": 10  // Optional, defaults to 10
  }
}
```

### STIX Objects
#### list_attack_patterns
Lists all attack patterns in the system.
```typescript
{
  "name": "list_attack_patterns",
  "arguments": {
    "first": 10  // Optional, defaults to 10
  }
}
```

#### get_campaign_by_name
Retrieves campaign information by name.
```typescript
{
  "name": "get_campaign_by_name",
  "arguments": {
    "name": "campaign-name"  // Required
  }
}
```

### System Management
#### list_connectors
Lists all system connectors.
```typescript
{
  "name": "list_connectors",
  "arguments": {}
}
```

#### list_status_templates
Lists all status templates.
```typescript
{
  "name": "list_status_templates",
  "arguments": {}
}
```

### File Operations
#### get_file_by_id
Retrieves file information by ID.
```typescript
{
  "name": "get_file_by_id",
  "arguments": {
    "id": "file-uuid"  // Required
  }
}
```

#### list_files
Lists all files in the system.
```typescript
{
  "name": "list_files",
  "arguments": {}
}
```

### Reference Data
#### list_marking_definitions
Lists all marking definitions.
```typescript
{
  "name": "list_marking_definitions",
  "arguments": {}
}
```

#### list_labels
Lists all available labels.
```typescript
{
  "name": "list_labels",
  "arguments": {}
}
```

## Contributing
Contributions are welcome! Please feel free to submit pull requests.

## License
MIT License

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "opencti-server",
  "version": "0.1.0",
  "description": "A Model Context Protocol server",
  "private": true,
  "type": "module",
  "bin": {
    "opencti-server": "./build/index.js"
  },
  "files": [
    "build"
  ],
  "scripts": {
    "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
    "prepare": "npm run build",
    "watch": "tsc --watch",
    "inspector": "npx @modelcontextprotocol/inspector build/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "0.6.0",
    "axios": "^1.7.9"
  },
  "devDependencies": {
    "@types/node": "^20.11.24",
    "typescript": "^5.3.3"
  }
}

```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml

startCommand:
  type: stdio
  configSchema:
    # JSON Schema defining the configuration options for the MCP.
    type: object
    required:
      - openctiUrl
      - openctiToken
    properties:
      openctiUrl:
        type: string
        description: The URL of the OpenCTI instance.
      openctiToken:
        type: string
        description: The API token for the OpenCTI instance.
  commandFunction:
    # A function that produces the CLI command to start the MCP on stdio.
    |-
    (config) => ({command: 'node', args: ['build/index.js'], env: {OPENCTI_URL: config.openctiUrl, OPENCTI_TOKEN: config.openctiToken}})

```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
# Use a Node.js image with the appropriate version
FROM node:16-alpine AS builder

# Set working directory
WORKDIR /app

# Copy package.json and package-lock.json for dependency installation
COPY package.json package.json

# Install dependencies
RUN npm install --ignore-scripts

# Copy the rest of the application source code
COPY . .

# Build the TypeScript project
RUN npm run build

# Prepare the runtime environment
FROM node:16-alpine AS release

# Set working directory
WORKDIR /app

# Copy built files and necessary configuration
COPY --from=builder /app/build /app/build
COPY --from=builder /app/package.json /app/package.json

# Set environment variables
ENV OPENCTI_URL=https://your-opencti-url
ENV OPENCTI_TOKEN=your-opencti-token

# Run the server
ENTRYPOINT ["node", "build/index.js"]

```

--------------------------------------------------------------------------------
/src/queries/references.ts:
--------------------------------------------------------------------------------

```typescript
export const ALL_MARKING_DEFINITIONS_QUERY = `
query AllMarkingDefinitions {
  markingDefinitions {
    edges {
      node {
        id
        standard_id
        entity_type
        definition_type
        definition
        x_opencti_order
        x_opencti_color
      }
    }
  }
}
`;

export const ALL_LABELS_QUERY = `
query AllLabels {
  labels {
    edges {
      node {
        id
        standard_id
        entity_type
        value
        color
      }
    }
  }
}
`;

export const ALL_EXTERNAL_REFERENCES_QUERY = `
query AllExternalReferences {
  externalReferences {
    edges {
      node {
        id
        standard_id
        entity_type
        source_name
        description
        url
        hash
        external_id
      }
    }
  }
}
`;

export const ALL_KILL_CHAIN_PHASES_QUERY = `
query AllKillChainPhases {
  killChainPhases {
    edges {
      node {
        id
        standard_id
        entity_type
        kill_chain_name
        phase_name
        x_opencti_order
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/queries/users.ts:
--------------------------------------------------------------------------------

```typescript
export const USER_BY_ID_QUERY = `
query UserById($id: String!) {
  user(id: $id) {
    id
    standard_id
    entity_type
    parent_types
    user_email
    name
    firstname
    lastname
    groups {
      edges {
        node {
          id
          name
        }
      }
    }
  }
}
`;

export const ALL_USERS_QUERY = `
query AllUsers {
  users {
    edges {
      node {
        id
        standard_id
        entity_type
        user_email
        name
        firstname
        lastname
        external
        created_at
        updated_at
      }
    }
  }
}
`;

export const ALL_GROUPS_QUERY = `
query AllGroups($first: Int, $after: ID) {
  groups(first: $first, after: $after) {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        name
        description
        members(first: 5) {
          edges {
            node {
              id
              name
              user_email
            }
          }
        }
      }
    }
  }
}
`;

export const ALL_ROLES_QUERY = `
query AllRoles {
  roles {
    edges {
      node {
        id
        standard_id
        entity_type
        name
        description
        created_at
        updated_at
      }
    }
  }
}
`;

export const ALL_CAPABILITIES_QUERY = `
query AllCapabilities {
  capabilities {
    edges {
      node {
        id
        standard_id
        entity_type
        name
        description
        attribute_order
        created_at
        updated_at
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/queries/metadata.ts:
--------------------------------------------------------------------------------

```typescript
export const FILE_BY_ID_QUERY = `
query FileById($id: String!) {
  file(id: $id) {
    id
    name
    size
    lastModified
    uploadStatus
  }
}
`;

export const ALL_FILES_QUERY = `
query AllFiles {
  importFiles(first: 100) {
    edges {
      node {
        id
        name
        size
        uploadStatus
        lastModified
        metaData {
          mimetype
          version
        }
      }
    }
  }
}
`;

export const ALL_INDEXED_FILES_QUERY = `
query AllIndexedFiles {
  indexedFiles {
    edges {
      node {
        id
        name
        file_id
        uploaded_at
        entity {
          id
          entity_type
          parent_types
          standard_id
        }
        searchOccurrences
      }
    }
  }
}
`;

export const ALL_LOGS_QUERY = `
query AllLogs {
  logs {
    edges {
      node {
        id
        entity_type
        event_type
        event_scope
        event_status
        timestamp
        user_id
        user {
          id
          name
          entity_type
        }
        context_uri
        context_data {
          entity_id
          entity_name
          entity_type
          from_id
          to_id
          message
          commit
          external_references {
            id
            source_name
            description
            url
            hash
            external_id
          }
        }
      }
    }
  }
}
`;

export const ALL_AUDITS_QUERY = `
query AllAudits {
  audits {
    edges {
      node {
        id
        entity_type
        event_type
        event_scope
        event_status
        timestamp
        user_id
        user {
          id
          name
          entity_type
        }
        context_uri
        context_data {
          entity_id
          entity_name
          entity_type
          from_id
          to_id
          message
          commit
          external_references {
            id
            source_name
            description
            url
            hash
            external_id
          }
        }
      }
    }
  }
}
`;

export const ALL_ATTRIBUTES_QUERY = `
query AllAttributes {
  runtimeAttributes {
    edges {
      node {
        id
        key
        value
      }
    }
  }
}
`;

export const ALL_SCHEMA_ATTRIBUTE_NAMES_QUERY = `
query AllSchemaAttributeNames {
  schemaAttributeNames(elementType: ["Report", "Note"]) {
    edges {
      node {
        id
        key
        value
      }
    }
  }
}
`;

export const ALL_FILTER_KEYS_SCHEMA_QUERY = `
query AllFilterKeysSchema {
  filterKeysSchema {
    entity_type
    filters_schema {
      filterKey
      filterDefinition {
        filterKey
        label
        type
        multiple
        subEntityTypes
        elementsForFilterValuesSearch
        subFilters {
          filterKey
          label
          type
          multiple
          subEntityTypes
          elementsForFilterValuesSearch
        }
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/queries/relationships.ts:
--------------------------------------------------------------------------------

```typescript
export const ALL_STIX_CORE_RELATIONSHIPS_QUERY = `
query AllStixCoreRelationships($first: Int, $after: ID) {
  stixCoreRelationships(first: $first, after: $after) {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        relationship_type
        confidence
        start_time
        stop_time
        from {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
        to {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
      }
    }
  }
}
`;

export const ALL_STIX_SIGHTING_RELATIONSHIPS_QUERY = `
query AllStixSightingRelationships($first: Int, $after: ID) {
  stixSightingRelationships(first: $first, after: $after) {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        relationship_type
        confidence
        first_seen
        last_seen
        from {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
        to {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
      }
    }
  }
}
`;

export const ALL_STIX_REF_RELATIONSHIPS_QUERY = `
query AllStixRefRelationships($first: Int, $after: ID) {
  stixRefRelationships(first: $first, after: $after) {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        relationship_type
        confidence
        from {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
        to {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
      }
    }
  }
}
`;

export const ALL_STIX_RELATIONSHIPS_QUERY = `
query AllStixRelationships {
  stixRelationships {
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        relationship_type
        confidence
        created_at
        updated_at
        from {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
        to {
          ... on StixDomainObject {
            id
            entity_type
            name
          }
          ... on StixCyberObservable {
            id
            entity_type
            observable_value
          }
        }
        objectMarking {
          id
          definition
          x_opencti_order
          x_opencti_color
        }
        createdBy {
          id
          name
          entity_type
        }
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/queries/reports.ts:
--------------------------------------------------------------------------------

```typescript
export const LATEST_REPORTS_QUERY = `
query LatestReport($first: Int) {
  reports(
    first: $first,
    orderBy: created,
    orderMode: desc
  ) {
    edges {
      node {
        # Basic fields
        id
        standard_id
        entity_type
        parent_types
        
        # Report specific fields
        name
        description
        content
        content_mapping
        report_types
        published
        confidence
        createdBy {
          id
          name
          entity_type
        }
        objectMarking {
          id
          definition
          x_opencti_order
          x_opencti_color
        }
        objectLabel {
          id
          value
          color
        }
        externalReferences {
          edges {
            node {
              id
              source_name
              description
              url
              hash
              external_id
            }
          }
        }
        
        # Relationships and objects
        objects(first: 500) {
          edges {
            node {
              ... on StixDomainObject {
                id
                entity_type
                parent_types
          created
                updated_at
                standard_id
                created
                revoked
                confidence
                lang
                status {
                  id
                  template {
                    name
                    color
                  }
                }
              }
              ... on StixCyberObservable {
                id
                entity_type
                parent_types
                observable_value
                x_opencti_description
                x_opencti_score
              }
              ... on StixCoreRelationship {
                id
                entity_type
                parent_types
                relationship_type
                description
                start_time
                stop_time
                from {
                  ... on StixDomainObject {
                    id
                    entity_type
                    parent_types
                    created_at
                    standard_id
                  }
                }
                to {
                  ... on StixDomainObject {
                    id
                    entity_type
                    parent_types
                    created_at
                    standard_id
                  }
                }
              }
            }
          }
        }
        
        # Additional metadata
        created
        modified
        created_at
        updated_at
        x_opencti_stix_ids
        status {
          id
          template {
            name
            color
          }
        }
        workflowEnabled
        
        # Container specific fields
        containersNumber {
          total
          count
        }
        containers {
          edges {
            node {
              id
              entity_type
              parent_types
              created_at
              standard_id
            }
          }
        }
      }
    }
  }
}
`;

export const SEARCH_MALWARE_QUERY = `
query Malware($search: String, $first: Int) {
  stixCoreObjects(
    search: $search,
    first: $first,
    types: ["Malware"]
  ) {
    edges {
      node {
        ... on Malware {
          id
          name
          description
          created
          modified
          malware_types
          is_family
          first_seen
          last_seen
        }
      }
    }
  }
}
`;

export const SEARCH_INDICATORS_QUERY = `
query Indicators($search: String, $first: Int) {
  stixCoreObjects(
    search: $search,
    first: $first,
    types: ["Indicator"]
  ) {
    edges {
      node {
        ... on Indicator {
          id
          name
          description
          created_at
          pattern
          valid_from
          valid_until
          x_opencti_score
        }
      }
    }
  }
}
`;

export const SEARCH_THREAT_ACTORS_QUERY = `
query ThreatActors($search: String, $first: Int) {
  stixCoreObjects(
    search: $search,
    first: $first,
    types: ["ThreatActorGroup"]
  ) {
    edges {
      node {
        ... on ThreatActorGroup {
          id
          name
          description
          created
          modified
          threat_actor_types
          first_seen
          last_seen
          sophistication
          resource_level
          roles
          goals
        }
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/queries/system.ts:
--------------------------------------------------------------------------------

```typescript
export const ALL_CONNECTORS_QUERY = `
query AllConnectors {
  connectors {
    id
    name
    active
    auto
    only_contextual
    playbook_compatible
    connector_type
    connector_scope
    connector_state
    connector_schema
    connector_schema_ui
    connector_state_reset
    connector_user_id
    updated_at
    created_at
    config {
      connection {
        host
        vhost
        use_ssl
        port
        user
        pass
      }
      listen
      listen_routing
      listen_exchange
      push
      push_routing
      push_exchange
    }
    works {
      id
      name
      status
    }
  }
}
`;

export const ALL_STATUS_TEMPLATES_QUERY = `
query AllStatusTemplates {
  statusTemplates {
    edges {
      node {
        id
        name
        color
        editContext {
          name
          focusOn
        }
        usages
      }
    }
  }
}
`;

export const ALL_STATUSES_QUERY = `
query AllStatuses {
  statuses {
    edges {
      node {
        id
        template_id
        template {
          id
          name
          color
        }
        type
        order
        disabled
      }
    }
  }
}
`;

export const ALL_SUB_TYPES_QUERY = `
query AllSubTypes {
  subTypes {
    edges {
      node {
        id
        label
        statuses {
          id
          template {
            id
            name
            color
          }
          type
          order
          disabled
        }
        workflowEnabled
        settings {
          id
          entity_type
          parent_types
          standard_id
        }
      }
    }
  }
}
`;

export const ALL_RETENTION_RULES_QUERY = `
query AllRetentionRules {
  retentionRules {
    edges {
      node {
        id
        standard_id
        name
        filters
        max_retention
        retention_unit
        last_execution_date
        last_deleted_count
        remaining_count
        scope
      }
    }
  }
}
`;

export const ALL_BACKGROUND_TASKS_QUERY = `
query AllBackgroundTasks {
  backgroundTasks {
    edges {
      node {
        id
        type
        initiator {
          id
          name
          entity_type
        }
        actions {
          type
          context {
            field
            type
            values
          }
        }
        created_at
        last_execution_date
        completed
        task_expected_number
        task_processed_number
        errors {
          id
          timestamp
          message
        }
      }
    }
  }
}
`;

export const ALL_FEEDS_QUERY = `
query AllFeeds {
  feeds {
    edges {
      node {
        id
        standard_id
        name
        description
        filters
        separator
        rolling_time
        feed_date_attribute
        include_header
        feed_types
        feed_attributes {
          attribute
          mappings {
            type
            attribute
          }
        }
        feed_public
        authorized_members {
          id
          name
          entity_type
          access_right
        }
      }
    }
  }
}
`;

export const ALL_TAXII_COLLECTIONS_QUERY = `
query AllTaxiiCollections {
  taxiiCollections {
    edges {
      node {
        id
        name
        description
        filters
        include_inferences
        score_to_confidence
        taxii_public
        authorized_members {
          id
          name
          entity_type
          access_right
        }
      }
    }
  }
}
`;

export const ALL_STREAM_COLLECTIONS_QUERY = `
query AllStreamCollections {
  streamCollections {
    edges {
      node {
        id
        name
        description
        filters
        stream_live
        stream_public
        authorized_members {
          id
          name
          entity_type
          access_right
        }
      }
    }
  }
}
`;

export const ALL_RULES_QUERY = `
query AllRules {
  rules {
    id
    name
    description
    activated
    category
    display {
      if {
        source
        source_color
        relation
        target
        target_color
        identifier
        identifier_color
        action
      }
      then {
        source
        source_color
        relation
        target
        target_color
        identifier
        identifier_color
        action
      }
    }
  }
}
`;

export const ALL_SYNCHRONIZERS_QUERY = `
query AllSynchronizers {
  synchronizers {
    edges {
      node {
        id
        name
        uri
        token
        stream_id
        user {
          id
          name
          entity_type
        }
        running
        current_state_date
        listen_deletion
        no_dependencies
        ssl_verify
        synchronized
        queue_messages
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/queries/stix_objects.ts:
--------------------------------------------------------------------------------

```typescript
export const REPORT_BY_ID_QUERY = `
query ReportById($id: String!) {
  report(id: $id) {
    id
    standard_id
    entity_type
    parent_types
    name
    description
    content
    content_mapping
    report_types
    published
    confidence
    createdBy {
      id
      name
      entity_type
    }
    objectMarking {
      id
      definition
      x_opencti_order
      x_opencti_color
    }
    objectLabel {
      id
      value
      color
    }
    externalReferences {
      edges {
        node {
          id
          source_name
          description
          url
          hash
          external_id
        }
      }
    }
    objects(first: 500) {
      edges {
        node {
          ... on StixDomainObject {
            id
            entity_type
            parent_types
            created
            updated_at
            standard_id
            created
            revoked
            confidence
            lang
            status {
              id
              template {
                name
                color
              }
            }
          }
          ... on StixCyberObservable {
            id
            entity_type
            parent_types
            observable_value
            x_opencti_description
            x_opencti_score
          }
          ... on StixCoreRelationship {
            id
            entity_type
            parent_types
            relationship_type
            description
            start_time
            stop_time
            from {
              ... on StixDomainObject {
                id
                entity_type
                parent_types
                created_at
                standard_id
              }
            }
            to {
              ... on StixDomainObject {
                id
                entity_type
                parent_types
                created_at
                standard_id
              }
            }
          }
        }
      }
    }
    created
    modified
    created_at
    updated_at
    x_opencti_stix_ids
    status {
      id
      template {
        name
        color
      }
    }
    workflowEnabled
    containersNumber {
      total
      count
    }
    containers {
      edges {
        node {
          id
          entity_type
          parent_types
          created_at
          standard_id
        }
      }
    }
  }
}
`;

export const ALL_ATTACK_PATTERNS_QUERY = `
query AllAttackPatterns($first: Int, $after: ID) {
  attackPatterns(first: $first, after: $after) {
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        name
        description
        x_mitre_id
        killChainPhases {
          id
          kill_chain_name
          phase_name
        }
        coursesOfAction {
          edges {
            node {
              id
              name
              description
            }
          }
        }
      }
    }
  }
}
`;

export const CAMPAIGN_BY_NAME_QUERY = `
query CampaignByName($name: Any!) {
  campaigns(
    first: 1,
    filters: {
      mode: and,
      filters: [
        {
          key: "name",
          values: [$name],
          operator: eq,
          mode: or
        }
      ],
      filterGroups: []
    }
  ) {
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        name
        description
        first_seen
        last_seen
        created
        modified
        created_at
        updated_at
      }
    }
  }
}
`;

export const ALL_STIX_CORE_OBJECTS_QUERY = `
query AllStixCoreObjects {
  stixCoreObjects {
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        representative {
          main
          secondary
        }
        x_opencti_stix_ids
        is_inferred
        spec_version
        created_at
        updated_at
        createdBy {
          id
          name
          entity_type
        }
        numberOfConnectedElement
        objectMarking {
          id
          definition
          x_opencti_order
          x_opencti_color
        }
        objectOrganization {
          id
          name
        }
        objectLabel {
          id
          value
          color
        }
        externalReferences {
          edges {
            node {
              id
              source_name
              description
              url
              hash
              external_id
            }
          }
        }
        containersNumber {
          total
          count
        }
        containers {
          edges {
            node {
              id
              entity_type
              parent_types
              created_at
              standard_id
            }
          }
        }
        reports {
          edges {
            node {
              id
              name
            }
          }
        }
        notes {
          edges {
            node {
              id
              content
            }
          }
        }
        opinions {
          edges {
            node {
              id
              opinion
            }
          }
        }
        observedData {
          edges {
            node {
              id
              first_observed
              last_observed
              number_observed
            }
          }
        }
        groupings {
          edges {
            node {
              id
              name
            }
          }
        }
        cases {
          edges {
            node {
              id
              name
            }
          }
        }
      }
    }
  }
}
`;

export const ALL_STIX_DOMAIN_OBJECTS_QUERY = `
query AllStixDomainObjects {
  stixDomainObjects {
    edges {
      node {
        id
        standard_id
        entity_type
        parent_types
        representative {
          main
          secondary
        }
        x_opencti_stix_ids
        is_inferred
        spec_version
        created_at
        updated_at
        createdBy {
          id
          name
          entity_type
        }
        numberOfConnectedElement
        objectMarking {
          id
          definition
          x_opencti_order
          x_opencti_color
        }
        objectOrganization {
          id
          name
        }
        objectLabel {
          id
          value
          color
        }
        externalReferences {
          edges {
            node {
              id
              source_name
              description
              url
              hash
              external_id
            }
          }
        }
        containersNumber {
          total
          count
        }
        containers {
          edges {
            node {
              id
              entity_type
              parent_types
              created_at
              standard_id
            }
          }
        }
        reports {
          edges {
            node {
              id
              name
            }
          }
        }
        notes {
          edges {
            node {
              id
              content
            }
          }
        }
        opinions {
          edges {
            node {
              id
              opinion
            }
          }
        }
        observedData {
          edges {
            node {
              id
              first_observed
              last_observed
              number_observed
            }
          }
        }
        groupings {
          edges {
            node {
              id
              name
            }
          }
        }
        cases {
          edges {
            node {
              id
              name
            }
          }
        }
        revoked
        confidence
        lang
        created
        modified
        x_opencti_graph_data
        objectAssignee {
          id
          name
          entity_type
        }
        objectParticipant {
          id
          name
          entity_type
        }
        status {
          id
          template {
            name
            color
          }
        }
        workflowEnabled
      }
    }
  }
}
`;

```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types.js';
import axios from 'axios';
import {
  LATEST_REPORTS_QUERY,
  SEARCH_MALWARE_QUERY,
  SEARCH_INDICATORS_QUERY,
  SEARCH_THREAT_ACTORS_QUERY,
} from './queries/reports.js';
import {
  USER_BY_ID_QUERY,
  ALL_USERS_QUERY,
  ALL_GROUPS_QUERY,
  ALL_ROLES_QUERY,
  ALL_CAPABILITIES_QUERY,
} from './queries/users.js';
import {
  REPORT_BY_ID_QUERY,
  ALL_ATTACK_PATTERNS_QUERY,
  CAMPAIGN_BY_NAME_QUERY,
  ALL_STIX_CORE_OBJECTS_QUERY,
  ALL_STIX_DOMAIN_OBJECTS_QUERY,
} from './queries/stix_objects.js';
import {
  ALL_STIX_CORE_RELATIONSHIPS_QUERY,
  ALL_STIX_SIGHTING_RELATIONSHIPS_QUERY,
  ALL_STIX_REF_RELATIONSHIPS_QUERY,
  ALL_STIX_RELATIONSHIPS_QUERY,
} from './queries/relationships.js';
import {
  ALL_CONNECTORS_QUERY,
  ALL_STATUS_TEMPLATES_QUERY,
  ALL_STATUSES_QUERY,
  ALL_SUB_TYPES_QUERY,
  ALL_RETENTION_RULES_QUERY,
  ALL_BACKGROUND_TASKS_QUERY,
  ALL_FEEDS_QUERY,
  ALL_TAXII_COLLECTIONS_QUERY,
  ALL_STREAM_COLLECTIONS_QUERY,
  ALL_RULES_QUERY,
  ALL_SYNCHRONIZERS_QUERY,
} from './queries/system.js';
import {
  FILE_BY_ID_QUERY,
  ALL_FILES_QUERY,
  ALL_INDEXED_FILES_QUERY,
  ALL_LOGS_QUERY,
  ALL_AUDITS_QUERY,
  ALL_ATTRIBUTES_QUERY,
  ALL_SCHEMA_ATTRIBUTE_NAMES_QUERY,
  ALL_FILTER_KEYS_SCHEMA_QUERY,
} from './queries/metadata.js';
import {
  ALL_MARKING_DEFINITIONS_QUERY,
  ALL_LABELS_QUERY,
  ALL_EXTERNAL_REFERENCES_QUERY,
  ALL_KILL_CHAIN_PHASES_QUERY,
} from './queries/references.js';

const OPENCTI_URL = process.env.OPENCTI_URL || 'http://localhost:8080';
const OPENCTI_TOKEN = process.env.OPENCTI_TOKEN;

if (!OPENCTI_TOKEN) {
  throw new Error('OPENCTI_TOKEN environment variable is required');
}

interface OpenCTIResponse {
  data: {
    stixObjects: Array<{
      id: string;
      name?: string;
      description?: string;
      created_at?: string;
      modified_at?: string;
      pattern?: string;
      valid_from?: string;
      valid_until?: string;
      x_opencti_score?: number;
      [key: string]: any;
    }>;
  };
}

class OpenCTIServer {
  private server: Server;
  private axiosInstance;

  constructor() {
    this.server = new Server(
      {
        name: 'opencti-server',
        version: '0.1.0',
      },
      {
        capabilities: {
          tools: {},
        },
      }
    );

    this.axiosInstance = axios.create({
      baseURL: OPENCTI_URL,
      headers: {
        'Authorization': `Bearer ${OPENCTI_TOKEN}`,
        'Content-Type': 'application/json',
      },
    });

    this.setupTools();
    
    this.server.onerror = (error) => console.error('[MCP Error]', error);
    process.on('SIGINT', async () => {
      await this.server.close();
      process.exit(0);
    });
  }

  private setupTools() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        // Reports
        {
          name: 'get_latest_reports',
          description: '獲取最新的OpenCTI報告',
          inputSchema: {
            type: 'object',
            properties: {
              first: {
                type: 'number',
                description: '返回結果數量限制',
                default: 10,
              },
            },
          },
        },
        {
          name: 'get_report_by_id',
          description: '根據ID獲取OpenCTI報告',
          inputSchema: {
            type: 'object',
            properties: {
              id: {
                type: 'string',
                description: '報告ID',
              },
            },
            required: ['id'],
          },
        },
        // Search
        {
          name: 'search_indicators',
          description: '搜尋OpenCTI中的指標',
          inputSchema: {
            type: 'object',
            properties: {
              query: {
                type: 'string',
                description: '搜尋關鍵字',
              },
              first: {
                type: 'number',
                description: '返回結果數量限制',
                default: 10,
              },
            },
            required: ['query'],
          },
        },
        {
          name: 'search_malware',
          description: '搜尋OpenCTI中的惡意程式',
          inputSchema: {
            type: 'object',
            properties: {
              query: {
                type: 'string',
                description: '搜尋關鍵字',
              },
              first: {
                type: 'number',
                description: '返回結果數量限制',
                default: 10,
              },
            },
            required: ['query'],
          },
        },
        {
          name: 'search_threat_actors',
          description: '搜尋OpenCTI中的威脅行為者',
          inputSchema: {
            type: 'object',
            properties: {
              query: {
                type: 'string',
                description: '搜尋關鍵字',
              },
              first: {
                type: 'number',
                description: '返回結果數量限制',
                default: 10,
              },
            },
            required: ['query'],
          },
        },
        // Users & Groups
        {
          name: 'get_user_by_id',
          description: '根據ID獲取使用者資訊',
          inputSchema: {
            type: 'object',
            properties: {
              id: {
                type: 'string',
                description: '使用者ID',
              },
            },
            required: ['id'],
          },
        },
        {
          name: 'list_users',
          description: '列出所有使用者',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
        {
          name: 'list_groups',
          description: '列出所有群組',
          inputSchema: {
            type: 'object',
            properties: {
              first: {
                type: 'number',
                description: '返回結果數量限制',
                default: 10,
              },
            },
          },
        },
        // STIX Objects
        {
          name: 'list_attack_patterns',
          description: '列出所有攻擊模式',
          inputSchema: {
            type: 'object',
            properties: {
              first: {
                type: 'number',
                description: '返回結果數量限制',
                default: 10,
              },
            },
          },
        },
        {
          name: 'get_campaign_by_name',
          description: '根據名稱獲取行動資訊',
          inputSchema: {
            type: 'object',
            properties: {
              name: {
                type: 'string',
                description: '行動名稱',
              },
            },
            required: ['name'],
          },
        },
        // System
        {
          name: 'list_connectors',
          description: '列出所有連接器',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
        {
          name: 'list_status_templates',
          description: '列出所有狀態模板',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
        // Files
        {
          name: 'get_file_by_id',
          description: '根據ID獲取檔案資訊',
          inputSchema: {
            type: 'object',
            properties: {
              id: {
                type: 'string',
                description: '檔案ID',
              },
            },
            required: ['id'],
          },
        },
        {
          name: 'list_files',
          description: '列出所有檔案',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
        // References
        {
          name: 'list_marking_definitions',
          description: '列出所有標記定義',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
        {
          name: 'list_labels',
          description: '列出所有標籤',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
      ],
    }));

    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      try {
        let query = '';
        let variables: any = {};

        switch (request.params.name) {
          // Reports
          case 'get_latest_reports':
            query = LATEST_REPORTS_QUERY;
            variables = {
              first: typeof request.params.arguments?.first === 'number' ? request.params.arguments.first : 10,
            };
            break;

          case 'get_report_by_id':
            if (!request.params.arguments?.id) {
              throw new McpError(ErrorCode.InvalidParams, 'Report ID is required');
            }
            query = REPORT_BY_ID_QUERY;
            variables = { id: request.params.arguments.id };
            break;

          // Search
          case 'search_indicators':
            if (!request.params.arguments?.query) {
              throw new McpError(ErrorCode.InvalidParams, 'Query parameter is required');
            }
            query = SEARCH_INDICATORS_QUERY;
            variables = {
              search: request.params.arguments.query,
              first: typeof request.params.arguments.first === 'number' ? request.params.arguments.first : 10,
            };
            break;

          case 'search_malware':
            if (!request.params.arguments?.query) {
              throw new McpError(ErrorCode.InvalidParams, 'Query parameter is required');
            }
            query = SEARCH_MALWARE_QUERY;
            variables = {
              search: request.params.arguments.query,
              first: typeof request.params.arguments.first === 'number' ? request.params.arguments.first : 10,
            };
            break;

          case 'search_threat_actors':
            if (!request.params.arguments?.query) {
              throw new McpError(ErrorCode.InvalidParams, 'Query parameter is required');
            }
            query = SEARCH_THREAT_ACTORS_QUERY;
            variables = {
              search: request.params.arguments.query,
              first: typeof request.params.arguments.first === 'number' ? request.params.arguments.first : 10,
            };
            break;

          // Users & Groups
          case 'get_user_by_id':
            if (!request.params.arguments?.id) {
              throw new McpError(ErrorCode.InvalidParams, 'User ID is required');
            }
            query = USER_BY_ID_QUERY;
            variables = { id: request.params.arguments.id };
            break;

          case 'list_users':
            query = ALL_USERS_QUERY;
            break;

          case 'list_groups':
            query = ALL_GROUPS_QUERY;
            variables = {
              first: typeof request.params.arguments?.first === 'number' ? request.params.arguments.first : 10,
            };
            break;

          // STIX Objects
          case 'list_attack_patterns':
            query = ALL_ATTACK_PATTERNS_QUERY;
            variables = {
              first: typeof request.params.arguments?.first === 'number' ? request.params.arguments.first : 10,
            };
            break;

          case 'get_campaign_by_name':
            if (!request.params.arguments?.name) {
              throw new McpError(ErrorCode.InvalidParams, 'Campaign name is required');
            }
            query = CAMPAIGN_BY_NAME_QUERY;
            variables = { name: request.params.arguments.name };
            break;

          // System
          case 'list_connectors':
            query = ALL_CONNECTORS_QUERY;
            break;

          case 'list_status_templates':
            query = ALL_STATUS_TEMPLATES_QUERY;
            break;

          // Files
          case 'get_file_by_id':
            if (!request.params.arguments?.id) {
              throw new McpError(ErrorCode.InvalidParams, 'File ID is required');
            }
            query = FILE_BY_ID_QUERY;
            variables = { id: request.params.arguments.id };
            break;

          case 'list_files':
            query = ALL_FILES_QUERY;
            break;

          // References
          case 'list_marking_definitions':
            query = ALL_MARKING_DEFINITIONS_QUERY;
            break;

          case 'list_labels':
            query = ALL_LABELS_QUERY;
            break;

          default:
            throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
        }

        const response = await this.axiosInstance.post('/graphql', {
          query,
          variables,
        });

        console.error('OpenCTI Response:', JSON.stringify(response.data, null, 2));
        
        if (!response.data?.data) {
          throw new McpError(
            ErrorCode.InternalError,
            `Invalid response format from OpenCTI: ${JSON.stringify(response.data)}`
          );
        }

        let formattedResponse;
        
        switch (request.params.name) {
          case 'get_latest_reports':
            formattedResponse = response.data.data.reports.edges.map((edge: any) => ({
              id: edge.node.id,
              name: edge.node.name || 'Unnamed',
              description: edge.node.description || '',
              content: edge.node.content || '',
              published: edge.node.published,
              confidence: edge.node.confidence,
              created: edge.node.created,
              modified: edge.node.modified,
              reportTypes: edge.node.report_types || [],
            }));
            break;

          case 'get_report_by_id':
            formattedResponse = {
              ...response.data.data.report,
              name: response.data.data.report.name || 'Unnamed',
              description: response.data.data.report.description || '',
            };
            break;

          case 'search_indicators':
          case 'search_malware':
          case 'search_threat_actors':
            formattedResponse = response.data.data.stixCoreObjects.edges.map((edge: any) => ({
              id: edge.node.id,
              name: edge.node.name || 'Unnamed',
              description: edge.node.description || '',
              created: edge.node.created,
              modified: edge.node.modified,
              type: edge.node.malware_types?.join(', ') || edge.node.threat_actor_types?.join(', ') || '',
              family: edge.node.is_family ? 'Yes' : 'No',
              firstSeen: edge.node.first_seen || '',
              lastSeen: edge.node.last_seen || '',
              pattern: edge.node.pattern || '',
              validFrom: edge.node.valid_from || '',
              validUntil: edge.node.valid_until || '',
              score: edge.node.x_opencti_score,
            }));
            break;

          case 'get_user_by_id':
            formattedResponse = {
              ...response.data.data.user,
              name: response.data.data.user.name || 'Unnamed',
            };
            break;

          case 'list_users':
            formattedResponse = response.data.data.users.edges.map((edge: any) => ({
              id: edge.node.id,
              name: edge.node.name || 'Unnamed',
              email: edge.node.user_email,
              firstname: edge.node.firstname,
              lastname: edge.node.lastname,
              created: edge.node.created_at,
              modified: edge.node.updated_at,
            }));
            break;

          case 'list_groups':
            formattedResponse = response.data.data.groups.edges.map((edge: any) => ({
              id: edge.node.id,
              name: edge.node.name || 'Unnamed',
              description: edge.node.description || '',
              members: edge.node.members?.edges?.map((memberEdge: any) => ({
                id: memberEdge.node.id,
                name: memberEdge.node.name,
                email: memberEdge.node.user_email,
              })) || [],
            }));
            break;

          case 'list_attack_patterns':
            formattedResponse = response.data.data.attackPatterns.edges.map((edge: any) => ({
              id: edge.node.id,
              name: edge.node.name || 'Unnamed',
              description: edge.node.description || '',
              created: edge.node.created_at,
              modified: edge.node.updated_at,
              killChainPhases: edge.node.killChainPhases?.edges?.map((phaseEdge: any) => ({
                id: phaseEdge.node.id,
                name: phaseEdge.node.phase_name,
              })) || [],
            }));
            break;

          case 'list_connectors':
            formattedResponse = response.data.data.connectors.map((connector: any) => ({
              id: connector.id,
              name: connector.name || 'Unnamed',
              type: connector.connector_type,
              scope: connector.connector_scope,
              state: connector.connector_state,
              active: connector.active,
              updated: connector.updated_at,
              created: connector.created_at,
            }));
            break;

          case 'list_status_templates':
            formattedResponse = response.data.data.statusTemplates.edges.map((edge: any) => ({
              id: edge.node.id,
              name: edge.node.name || 'Unnamed',
              color: edge.node.color,
              usages: edge.node.usages,
            }));
            break;

          case 'list_marking_definitions':
            formattedResponse = response.data.data.markingDefinitions.edges.map((edge: any) => ({
              id: edge.node.id,
              definition: edge.node.definition,
              color: edge.node.x_opencti_color,
              order: edge.node.x_opencti_order,
            }));
            break;

          case 'list_labels':
            formattedResponse = response.data.data.labels.edges.map((edge: any) => ({
              id: edge.node.id,
              value: edge.node.value,
              color: edge.node.color,
            }));
            break;

          default:
            formattedResponse = response.data.data;
        }

        return {
          content: [{
            type: 'text',
            text: JSON.stringify(formattedResponse, null, 2)
          }]
        };
      } catch (error) {
        if (axios.isAxiosError(error)) {
          console.error('Axios Error:', error.response?.data);
          return {
            content: [{
              type: 'text',
              text: `OpenCTI API error: ${JSON.stringify(error.response?.data) || error.message}`
            }],
            isError: true,
          };
        }
        throw error;
      }
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error('OpenCTI MCP server running on stdio');
  }
}

const server = new OpenCTIServer();
server.run().catch(console.error);

```
Page 1/2FirstPrevNextLast