Skip to main content
Glama
sifue

ZEN University Syllabus MCP Server

by sifue

get-a-subject-with-detail

Retrieve detailed course information from ZEN University's syllabus by specifying enrollment year and search keywords to find relevant subjects.

Instructions

Retrieve detailed a course information from the ZEN University syllabus. The numeric intended year of enrollment (enrollment_grade (optional)) and the freeword parameter (freeword) must be specified. The freeword parameter is intended for searching course names and similar keywords.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
enrollment_gradeNo year of enrollment (e.g. 1, 2, 3, 4)
freewordYesthe freeword search parameter (e.g. 'ITリテラシー')

Implementation Reference

  • The handler function for the 'get-a-subject-with-detail' tool. It takes enrollment_grade and freeword parameters, fetches matching subjects from the ZEN University syllabus API using fetchAllPages, filters and formats the data, and returns a text response with a list of subjects and detailed info for the first one.
    async ({ enrollment_grade, freeword }) => {
      try {
        const options: FetchOptions = {};
    
        if (enrollment_grade) {
          options.enrollment_grade = enrollment_grade.toString();
        }
    
        if (freeword) {
          options.freeword = freeword;
        }
    
        const apiResponse = await fetchAllPages(options);
        
        // 必要なフィールドのみを抽出
        const filteredSubjects = apiResponse.subjects.map(subject => ({
          code: subject.code,
          name: subject.name,
          description: subject.description,
          thumbnailUrl: subject.thumbnailUrl,
          openingYear: subject.openingYear,
          faculty: subject.faculty ? subject.faculty.map(f => ({
            id: f.id,
            name: f.name,
            reading: f.reading,
            isForeign: f.isForeign,
            title: f.title,
            expertise: f.expertise,
            avatarUrl: f.avatarUrl
          })) : [],
          metadata: {
            enrollmentGrade: subject.metadata.enrollmentGrade,
            teachingMethod: subject.metadata.teachingMethod,
            subjectRequirement: subject.metadata.subjectRequirement,
            evaluationSystem: subject.metadata.evaluationSystem,
            credit: subject.metadata.credit,
            quarters: subject.metadata.quarters,
            objective: subject.metadata.objective,
            specialNotes: subject.metadata.specialNotes,
            coursePlans: subject.metadata.coursePlans ? subject.metadata.coursePlans.map(plan => ({
              title: plan.title,
              description: plan.description,
              sections: plan.sections
            })) : []
          },
          subjectCategoryIds: subject.subjectCategoryIds || []
        }));
        
        // フィルタリングした結果を新しいレスポンスオブジェクトに設定
        const filteredResponse: ApiResponse = {
          totalCount: apiResponse.totalCount,
          pageSize: apiResponse.pageSize,
          page: apiResponse.page,
          totalPages: apiResponse.totalPages,
          relatedTags: apiResponse.relatedTags,
          subjects: filteredSubjects
        };
        
        // 科目名の一覧と最初の科目の詳細のみを表示するテキスト形式に変換
        const formattedText = formatSubjectsWithFirstDetailToText(filteredResponse);
        
        return {
          content: [
            {
              type: "text",
              text: formattedText,
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error: ${error}`,
            },
          ],
        };
      }
    },
  • The input schema for the tool using Zod validation, defining optional enrollment_grade (1-4) and required freeword string.
    {
      enrollment_grade: z.number().min(1).max(4).describe(" year of enrollment (e.g. 1, 2, 3, 4)").optional(),
      freeword: z.string().describe("the freeword search parameter (e.g. 'ITリテラシー')"),
    },
  • src/index.ts:373-461 (registration)
    The registration of the 'get-a-subject-with-detail' tool on the MCP server, including name, description, schema, and handler.
    server.tool(
      "get-a-subject-with-detail",
      "Retrieve detailed a course information from the ZEN University syllabus. The numeric intended year of enrollment (enrollment_grade (optional)) and the freeword parameter (freeword) must be specified. The freeword parameter is intended for searching course names and similar keywords.",
      {
        enrollment_grade: z.number().min(1).max(4).describe(" year of enrollment (e.g. 1, 2, 3, 4)").optional(),
        freeword: z.string().describe("the freeword search parameter (e.g. 'ITリテラシー')"),
      },
    
      async ({ enrollment_grade, freeword }) => {
        try {
          const options: FetchOptions = {};
    
          if (enrollment_grade) {
            options.enrollment_grade = enrollment_grade.toString();
          }
    
          if (freeword) {
            options.freeword = freeword;
          }
    
          const apiResponse = await fetchAllPages(options);
          
          // 必要なフィールドのみを抽出
          const filteredSubjects = apiResponse.subjects.map(subject => ({
            code: subject.code,
            name: subject.name,
            description: subject.description,
            thumbnailUrl: subject.thumbnailUrl,
            openingYear: subject.openingYear,
            faculty: subject.faculty ? subject.faculty.map(f => ({
              id: f.id,
              name: f.name,
              reading: f.reading,
              isForeign: f.isForeign,
              title: f.title,
              expertise: f.expertise,
              avatarUrl: f.avatarUrl
            })) : [],
            metadata: {
              enrollmentGrade: subject.metadata.enrollmentGrade,
              teachingMethod: subject.metadata.teachingMethod,
              subjectRequirement: subject.metadata.subjectRequirement,
              evaluationSystem: subject.metadata.evaluationSystem,
              credit: subject.metadata.credit,
              quarters: subject.metadata.quarters,
              objective: subject.metadata.objective,
              specialNotes: subject.metadata.specialNotes,
              coursePlans: subject.metadata.coursePlans ? subject.metadata.coursePlans.map(plan => ({
                title: plan.title,
                description: plan.description,
                sections: plan.sections
              })) : []
            },
            subjectCategoryIds: subject.subjectCategoryIds || []
          }));
          
          // フィルタリングした結果を新しいレスポンスオブジェクトに設定
          const filteredResponse: ApiResponse = {
            totalCount: apiResponse.totalCount,
            pageSize: apiResponse.pageSize,
            page: apiResponse.page,
            totalPages: apiResponse.totalPages,
            relatedTags: apiResponse.relatedTags,
            subjects: filteredSubjects
          };
          
          // 科目名の一覧と最初の科目の詳細のみを表示するテキスト形式に変換
          const formattedText = formatSubjectsWithFirstDetailToText(filteredResponse);
          
          return {
            content: [
              {
                type: "text",
                text: formattedText,
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: `Error: ${error}`,
              },
            ],
          };
        }
      },
    );
  • Helper function that fetches all pages of the syllabus API based on options (freeword, enrollment_grade) and merges all subjects into a single response.
    async function fetchAllPages(options?: FetchOptions) {
      // まず最初のページを取得
      const firstPageUrl = createUrl(0, options);
      const firstResponse = await fetch(firstPageUrl);
      if (!firstResponse.ok) {
        throw new Error(`APIリクエストに失敗しました: ${firstResponse.status} ${firstResponse.statusText}`);
      }
    
      const firstData = (await firstResponse.json()) as ApiResponse;
      const allSubjects = [...firstData.subjects];
      const { totalPages, totalCount, pageSize, relatedTags } = firstData;
    
      // 2ページ目以降を順次取得 (page=1 ~ totalPages-1)
      for (let page = 1; page < totalPages; page++) {
        const url = createUrl(page, options);
        const response = await fetch(url);
    
        if (!response.ok) {
          throw new Error(`APIリクエストに失敗しました: ${response.status} ${response.statusText}`);
        }
    
        const data = (await response.json()) as ApiResponse;
        allSubjects.push(...data.subjects);
      }
    
      // 単一のオブジェクトとしてまとめる
      const mergedData = {
        totalCount,
        pageSize,
        page: 0, // 全ページのデータを結合した結果なので、page=0 とする
        totalPages,
        relatedTags,
        subjects: allSubjects,
      };
    
      return mergedData;
    }
  • Helper function that formats the API response into text: list of all matching subjects and detailed markdown for the first one.
    function formatSubjectsWithFirstDetailToText(apiResponse: ApiResponse): string {
      if (apiResponse.subjects.length === 0) {
        return `検索結果: 0件の科目が見つかりました\n\n`;
      }
    
      let text = `検索結果: ${apiResponse.totalCount}件の科目が見つかりました\n\n`;
      
      // 科目名の一覧を表示
      text += `## 科目一覧\n`;
      apiResponse.subjects.forEach((subject, index) => {
        text += `${index + 1}. ${subject.name} (${subject.code})\n`;
      });
      
      text += `\n${'='.repeat(50)}\n\n`;
      
      // 最初の科目の詳細を表示
      text += `## 最初の科目の詳細\n\n`;
      text += formatSubjectToText(apiResponse.subjects[0]);
      
      // 他の科目の詳細を見るには再度問い合わせるように促すメッセージ
      if (apiResponse.subjects.length > 1) {
        text += `\n${'='.repeat(50)}\n\n`;
        text += `※ 他の科目の詳細を見るには、科目名を指定して再度問い合わせてください。\n`;
      }
      
      return text;
    }

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/sifue/zen-syllabus-mcp'

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