fix #424: clarify MCP reasoning workflow
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
<main class="container py-4">
|
<main class="container py-4">
|
||||||
<div class="page-title">
|
<div class="page-title">
|
||||||
<h1>MCP Reasoning</h1>
|
<h1>MCP Reasoning</h1>
|
||||||
<p>보호 객체 ORDS 호출을 내부 도구로 실행하고, 실행 증거를 OpenAI 호환 모델에 전달해 권한 결과를 해석합니다.</p>
|
<p>Bearer Token으로 보호 객체를 조회한 뒤, 반환된 행과 NULL 처리 결과를 모델이 설명합니다.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="alert alert-warning" th:if="${runtimeError}">
|
<div class="alert alert-warning" th:if="${runtimeError}">
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<section class="content-band">
|
<section class="content-band">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<h2>도구 실행</h2>
|
<h2>권한 결과 해석</h2>
|
||||||
<a class="btn btn-sm btn-outline-secondary" href="/mcp/tools" target="_blank" rel="noreferrer">도구 JSON</a>
|
<a class="btn btn-sm btn-outline-secondary" href="/mcp/tools" target="_blank" rel="noreferrer">도구 JSON</a>
|
||||||
</div>
|
</div>
|
||||||
<form hx-post="/mcp-reasoning" hx-target="#mcp-result" hx-swap="innerHTML" class="form-grid">
|
<form hx-post="/mcp-reasoning" hx-target="#mcp-result" hx-swap="innerHTML" class="form-grid">
|
||||||
@@ -29,11 +29,11 @@
|
|||||||
<input class="form-control" name="bearerToken" type="password" autocomplete="off" required>
|
<input class="form-control" name="bearerToken" type="password" autocomplete="off" required>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
도구
|
조회 대상
|
||||||
<select class="form-select" name="objectId" required>
|
<select class="form-select" id="mcp-reasoning-object" name="objectId" required>
|
||||||
<option th:each="tool : ${tools}"
|
<option th:each="tool : ${tools}"
|
||||||
th:value="${tool.objectId()}"
|
th:value="${tool.objectId()}"
|
||||||
th:text="${tool.name() + ' / ' + tool.displayName()}"></option>
|
th:text="${tool.displayName() + ' / ' + tool.ordsPath()}"></option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
@@ -42,35 +42,61 @@
|
|||||||
</label>
|
</label>
|
||||||
<label class="span-2">
|
<label class="span-2">
|
||||||
질문
|
질문
|
||||||
<textarea class="form-control" name="question" rows="3"
|
<textarea class="form-control" id="mcp-reasoning-question" name="question" rows="3"
|
||||||
placeholder="예: 이 토큰으로 어떤 행이 보이고 어떤 컬럼이 NULL 처리됐는지 요약해줘."></textarea>
|
placeholder="비워도 기본 질문으로 실행됩니다."></textarea>
|
||||||
</label>
|
</label>
|
||||||
|
<div class="question-presets span-2" aria-label="질문 예시">
|
||||||
|
<button class="btn rw-btn-secondary question-preset" type="button"
|
||||||
|
data-question="이 토큰으로 조회 가능한 행 수와 주요 값을 먼저 요약하고, 어떤 VPD 조건이 적용된 결과인지 추정해줘.">
|
||||||
|
조회 결과 요약
|
||||||
|
</button>
|
||||||
|
<button class="btn rw-btn-secondary question-preset" type="button"
|
||||||
|
data-question="반환된 행에서 NULL 처리된 컬럼이 있는지 확인하고, 민감 컬럼 권한 관점에서 설명해줘.">
|
||||||
|
NULL 처리 확인
|
||||||
|
</button>
|
||||||
|
<button class="btn rw-btn-secondary question-preset" type="button"
|
||||||
|
data-question="이 토큰이 전체 조회 권한인지, 부서/본인/조건 제한 권한인지 결과 증거를 기준으로 판단해줘.">
|
||||||
|
권한 범위 판단
|
||||||
|
</button>
|
||||||
|
<button class="btn rw-btn-secondary question-preset" type="button"
|
||||||
|
data-question="운영자가 확인해야 할 이상 징후나 설정 불일치 가능성을 짧게 정리해줘.">
|
||||||
|
운영 점검 요약
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<button class="btn rw-btn-primary" type="submit">Reasoning 실행</button>
|
<button class="btn rw-btn-primary" type="submit">Reasoning 실행</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="content-band">
|
<section class="content-band">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<h2>등록된 도구</h2>
|
<h2>조회 가능 대상</h2>
|
||||||
<span class="badge text-bg-secondary" th:text="${#lists.size(tools)}">0</span>
|
<span class="badge text-bg-secondary" th:text="${#lists.size(tools)}">0</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-sm align-middle">
|
<table class="table table-sm align-middle">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>선택</th>
|
||||||
<th>Object</th>
|
<th>Object</th>
|
||||||
<th>ORDS Path</th>
|
<th>ORDS Path</th>
|
||||||
|
<th>MCP Tool</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr th:each="tool : ${tools}">
|
<tr th:each="tool : ${tools}">
|
||||||
<td><code th:text="${tool.name()}">tool</code></td>
|
<td>
|
||||||
|
<button class="btn btn-sm rw-btn-secondary reasoning-object-preset"
|
||||||
|
type="button"
|
||||||
|
th:attr="data-object-id=${tool.objectId()},data-question=${tool.displayName() + '에서 이 토큰으로 조회 가능한 행과 NULL 처리 컬럼을 요약해줘.'}">
|
||||||
|
선택
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
<td th:text="${tool.displayName()}">ADMIN.TABLE</td>
|
<td th:text="${tool.displayName()}">ADMIN.TABLE</td>
|
||||||
<td><code th:text="${tool.ordsPath()}">path</code></td>
|
<td><code th:text="${tool.ordsPath()}">path</code></td>
|
||||||
|
<td><code th:text="${tool.name()}">tool</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr th:if="${#lists.isEmpty(tools)}">
|
<tr th:if="${#lists.isEmpty(tools)}">
|
||||||
<td colspan="3" class="text-muted">등록된 보호 객체 도구가 없습니다.</td>
|
<td colspan="4" class="text-muted">등록된 보호 객체 도구가 없습니다.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -81,5 +107,24 @@
|
|||||||
<div class="text-muted">Reasoning 결과가 여기에 표시됩니다.</div>
|
<div class="text-muted">Reasoning 결과가 여기에 표시됩니다.</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
<script>
|
||||||
|
document.querySelectorAll('.question-preset').forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const question = document.getElementById('mcp-reasoning-question');
|
||||||
|
question.value = button.dataset.question || '';
|
||||||
|
question.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('.reasoning-object-preset').forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const objectSelect = document.getElementById('mcp-reasoning-object');
|
||||||
|
const question = document.getElementById('mcp-reasoning-question');
|
||||||
|
objectSelect.value = button.dataset.objectId || objectSelect.value;
|
||||||
|
question.value = button.dataset.question || question.value;
|
||||||
|
question.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user