Skip to main content
Glama
pythagraph

Pythagraph RED MCP Server

by pythagraph

get_graph_data

Retrieve detailed graph data, including nodes, edges, and statistics, formatted as tables and descriptions. Use to analyze graph structure and gain insights from the Pythagraph RED API.

Instructions

Retrieve detailed graph data from Pythagraph RED API. Returns comprehensive information including nodes, edges, statistics, and metadata formatted as tables and descriptions. Perfect for analyzing graph structure and getting detailed insights.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
graphIdYesThe unique identifier for the graph to retrieve

Implementation Reference

  • Handler logic for the 'get_graph_data' tool within the CallToolRequestSchema request handler. It validates the input arguments using the schema, fetches the graph data from the API, formats it into a Markdown table with statistics, and returns it as text content.
    case "get_graph_data": {
      const parsed = GetGraphDataArgsSchema.safeParse(args);
      if (!parsed.success) {
        throw new Error(`Invalid arguments for get_graph_data: ${parsed.error}`);
      }
    
      const graphData = await fetchGraphData(parsed.data.graphId);
      const formattedData = formatGraphDataAsTable(graphData);
    
      return {
        content: [{ type: "text", text: formattedData }],
      };
    }
  • Zod schema defining the input for the get_graph_data tool: requires a graphId string.
    const GetGraphDataArgsSchema = z.object({
      graphId: z.string().describe('The unique identifier for the graph to retrieve'),
    });
  • index.ts:260-263 (registration)
    Tool registration in the list returned by ListToolsRequestSchema handler, including name, description, and input schema reference.
      name: "get_graph_data",
      description: "Retrieve detailed graph data from Pythagraph RED API. Returns comprehensive information including nodes, edges, statistics, and metadata formatted as tables and descriptions. Perfect for analyzing graph structure and getting detailed insights.",
      inputSchema: zodToJsonSchema(GetGraphDataArgsSchema) as ToolInput,
    },
  • Helper function to fetch raw graph data from the Pythagraph RED API endpoint given a graphId.
    async function fetchGraphData(graphId: string): Promise<PythagraphResponse> {
      const url = `${API_BASE_URL}?graphId=${encodeURIComponent(graphId)}`;
      
      try {
        const response = await fetch(url, {
          method: 'GET',
          headers: {
            'Accept': 'application/json',
            'User-Agent': 'MCP-PythagraphRED-Server/0.1.0',
          },
    //      timeout: 30000, // 30 second timeout
        });
    
        if (!response.ok) {
          throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }
    
        const data = await response.json() as PythagraphResponse;
        
        if (data.message !== 'OK') {
          throw new Error(`API Error: ${data.message}`);
        }
        
        return data;
      } catch (error) {
        if (error instanceof Error) {
          throw new Error(`Failed to fetch graph data: ${error.message}`);
        }
        throw new Error('Failed to fetch graph data: Unknown error');
      }
    }
  • Helper function that formats the fetched PythagraphResponse into a comprehensive Markdown report with overview, basic info table, data table, data sources, and statistics.
    function formatGraphDataAsTable(data: PythagraphResponse): string {
      let result = "";
    
      // Graph Overview
      result += `# ${data.graphNm}\n\n`;
      
      // Graph Details (HTML을 텍스트로 변환)
      if (data.graphDet) {
        const cleanDescription = data.graphDet
          .replace(/<[^>]*>/g, '') // HTML 태그 제거
          .replace(/"/g, '"') // HTML 엔티티 변환
          .replace(//g, '') // 특수 문자 제거
          .trim();
        result += `**설명**: ${cleanDescription}\n\n`;
      }
    
      // Basic Information
      result += "## 📊 기본 정보\n\n";
      result += "| 항목 | 값 |\n";
      result += "|------|----|\n";
      result += `| Graph ID | ${data.graphId} |\n`;
      result += `| 단위 구분 | ${data.unitDivNm} |\n`;
      result += `| 단위명 | ${data.unitNm} |\n`;
      result += `| 등록자 | ${data.regUser} |\n`;
      result += `| 등록시간 | ${data.regTime} |\n`;
      result += `| 데이터 건수 | ${data.graphData.length}건 |\n`;
    
      // Data Sources
      if (data.dataSrc || data.dataOrg || data.link) {
        result += "\n## 🔗 데이터 출처\n\n";
        result += "| 구분 | URL |\n";
        result += "|------|-----|\n";
        if (data.dataSrc) result += `| 데이터 소스 | ${data.dataSrc} |\n`;
        if (data.dataOrg) result += `| 데이터 기관 | ${data.dataOrg} |\n`;
        if (data.link) result += `| 링크 | ${data.link} |\n`;
      }
    
      // Main Data Table
      if (data.graphData && data.graphData.length > 0 && data.cols) {
        result += "\n## 📈 데이터 테이블\n\n";
        
        // 테이블 헤더 생성
        const headers = data.cols.join(" | ");
        const separator = data.cols.map(() => "------").join(" | ");
        
        result += `| ${headers} |\n`;
        result += `| ${separator} |\n`;
        
        // 데이터 행 생성
        for (const row of data.graphData) {
          if (row.length === data.cols.length) {
            const formattedRow = row.map((cell, index) => {
              // 값 컬럼인 경우 숫자로 포맷팅
              if (data.cols[index].includes('값') && !isNaN(parseFloat(cell))) {
                const numValue = parseFloat(cell);
                return (numValue * 100).toFixed(1) + '%'; // 비율을 퍼센트로 변환
              }
              return cell;
            }).join(" | ");
            result += `| ${formattedRow} |\n`;
          }
        }
      }
    
      // Statistics
      if (data.graphData && data.graphData.length > 0) {
        result += "\n## 📊 통계 분석\n\n";
        
        // 값 컬럼 찾기
        const valueColumnIndex = data.cols.findIndex(col => col.includes('값'));
        
        if (valueColumnIndex !== -1) {
          const values = data.graphData
            .map(row => parseFloat(row[valueColumnIndex]))
            .filter(val => !isNaN(val));
          
          if (values.length > 0) {
            const total = values.reduce((sum, val) => sum + val, 0);
            const average = total / values.length;
            const max = Math.max(...values);
            const min = Math.min(...values);
            
            result += "| 통계 항목 | 값 |\n";
            result += "|-----------|----|\n";
            result += `| 총합 | ${(total * 100).toFixed(1)}% |\n`;
            result += `| 평균 | ${(average * 100).toFixed(1)}% |\n`;
            result += `| 최댓값 | ${(max * 100).toFixed(1)}% |\n`;
            result += `| 최솟값 | ${(min * 100).toFixed(1)}% |\n`;
            result += `| 데이터 개수 | ${values.length}개 |\n`;
          }
        }
      }
    
      return result;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions the return format ('formatted as tables and descriptions') and purpose ('analyzing graph structure'), but lacks critical details such as whether this is a read-only operation, potential rate limits, authentication requirements, or error handling. For a tool with no annotations, this leaves significant gaps in understanding its behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded, with two sentences that efficiently convey the tool's purpose and usage. The first sentence covers retrieval and return format, while the second provides context. There's minimal waste, though the phrase 'Perfect for' could be slightly more formal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (retrieving detailed graph data with 1 parameter), no annotations, and no output schema, the description is moderately complete. It covers the purpose and return format but lacks details on behavioral traits and output structure. For a tool with no structured output information, more elaboration on what 'comprehensive information' includes would be beneficial, making it adequate but with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, with the single parameter 'graphId' documented as 'The unique identifier for the graph to retrieve'. The description adds no additional parameter information beyond what the schema provides, such as format examples or constraints. With high schema coverage, the baseline score of 3 is appropriate, as the description doesn't compensate but doesn't need to given the schema's completeness.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with a specific verb ('Retrieve') and resource ('detailed graph data from Pythagraph RED API'), and distinguishes it from the sibling tool 'get_graph_summary' by emphasizing 'detailed' and 'comprehensive information'. However, it doesn't explicitly contrast with the sibling tool's functionality beyond implying more detail.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context by stating it's 'Perfect for analyzing graph structure and getting detailed insights', which suggests when to use this tool. However, it doesn't provide explicit guidance on when to choose this over 'get_graph_summary' or any exclusions, leaving the distinction somewhat vague.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

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/pythagraph/pythagraph-red-mcp'

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